ust-fd: Add close_range declaration
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
diff --git a/liblttng-ust/lttng-ust-statedump.c b/liblttng-ust/lttng-ust-statedump.c
deleted file mode 100644 (file)
index 98b80b3..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
- * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
- * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- */
-
-#define _LGPL_SOURCE
-#include <link.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <ust-elf.h>
-#include <ust-helper.h>
-#include "lttng-tracer-core.h"
-#include "lttng-ust-statedump.h"
-#include "jhash.h"
-#include "getenv.h"
-#include "compat.h"
-#include "ust-events-internal.h"
-
-#define TRACEPOINT_DEFINE
-#include "ust_lib.h"                           /* Only define. */
-
-#define TRACEPOINT_CREATE_PROBES
-#define TP_SESSION_CHECK
-#include "lttng-ust-statedump-provider.h"      /* Define and create probes. */
-
-struct dl_iterate_data {
-       int exec_found;
-       bool first;
-       bool cancel;
-};
-
-struct bin_info_data {
-       void *base_addr_ptr;
-       char resolved_path[PATH_MAX];
-       char *dbg_file;
-       uint8_t *build_id;
-       uint64_t memsz;
-       size_t build_id_len;
-       int vdso;
-       uint32_t crc;
-       uint8_t is_pic;
-       uint8_t has_build_id;
-       uint8_t has_debug_link;
-};
-
-struct lttng_ust_dl_node {
-       struct bin_info_data bin_data;
-       struct cds_hlist_node node;
-       bool traced;
-       bool marked;
-};
-
-#define UST_DL_STATE_HASH_BITS 8
-#define UST_DL_STATE_TABLE_SIZE        (1 << UST_DL_STATE_HASH_BITS)
-struct cds_hlist_head dl_state_table[UST_DL_STATE_TABLE_SIZE];
-
-typedef void (*tracepoint_cb)(struct lttng_ust_session *session, void *priv);
-
-static
-struct lttng_ust_dl_node *alloc_dl_node(const struct bin_info_data *bin_data)
-{
-       struct lttng_ust_dl_node *e;
-
-       e = zmalloc(sizeof(struct lttng_ust_dl_node));
-       if (!e)
-               return NULL;
-       if (bin_data->dbg_file) {
-               e->bin_data.dbg_file = strdup(bin_data->dbg_file);
-               if (!e->bin_data.dbg_file)
-                       goto error;
-       }
-       if (bin_data->build_id) {
-               e->bin_data.build_id = zmalloc(bin_data->build_id_len);
-               if (!e->bin_data.build_id)
-                       goto error;
-               memcpy(e->bin_data.build_id, bin_data->build_id,
-                               bin_data->build_id_len);
-       }
-       e->bin_data.base_addr_ptr = bin_data->base_addr_ptr;
-       memcpy(e->bin_data.resolved_path, bin_data->resolved_path, PATH_MAX);
-       e->bin_data.memsz = bin_data->memsz;
-       e->bin_data.build_id_len = bin_data->build_id_len;
-       e->bin_data.vdso = bin_data->vdso;
-       e->bin_data.crc = bin_data->crc;
-       e->bin_data.is_pic = bin_data->is_pic;
-       e->bin_data.has_build_id = bin_data->has_build_id;
-       e->bin_data.has_debug_link = bin_data->has_debug_link;
-       return e;
-
-error:
-       free(e->bin_data.build_id);
-       free(e->bin_data.dbg_file);
-       free(e);
-       return NULL;
-}
-
-static
-void free_dl_node(struct lttng_ust_dl_node *e)
-{
-       free(e->bin_data.build_id);
-       free(e->bin_data.dbg_file);
-       free(e);
-}
-
-/* Return 0 if same, nonzero if not. */
-static
-int compare_bin_data(const struct bin_info_data *a,
-               const struct bin_info_data *b)
-{
-       if (a->base_addr_ptr != b->base_addr_ptr)
-               return -1;
-       if (strcmp(a->resolved_path, b->resolved_path) != 0)
-               return -1;
-       if (a->dbg_file && !b->dbg_file)
-               return -1;
-       if (!a->dbg_file && b->dbg_file)
-               return -1;
-       if (a->dbg_file && strcmp(a->dbg_file, b->dbg_file) != 0)
-               return -1;
-       if (a->build_id && !b->build_id)
-               return -1;
-       if (!a->build_id && b->build_id)
-               return -1;
-       if (a->build_id_len != b->build_id_len)
-               return -1;
-       if (a->build_id &&
-                       memcmp(a->build_id, b->build_id, a->build_id_len) != 0)
-               return -1;
-       if (a->memsz != b->memsz)
-               return -1;
-       if (a->vdso != b->vdso)
-               return -1;
-       if (a->crc != b->crc)
-               return -1;
-       if (a->is_pic != b->is_pic)
-               return -1;
-       if (a->has_build_id != b->has_build_id)
-               return -1;
-       if (a->has_debug_link != b->has_debug_link)
-               return -1;
-       return 0;
-}
-
-static
-struct lttng_ust_dl_node *find_or_create_dl_node(struct bin_info_data *bin_data)
-{
-       struct cds_hlist_head *head;
-       struct lttng_ust_dl_node *e;
-       unsigned int hash;
-       bool found = false;
-
-       hash = jhash(&bin_data->base_addr_ptr,
-               sizeof(bin_data->base_addr_ptr), 0);
-       head = &dl_state_table[hash & (UST_DL_STATE_TABLE_SIZE - 1)];
-       cds_hlist_for_each_entry_2(e, head, node) {
-               if (compare_bin_data(&e->bin_data, bin_data) != 0)
-                       continue;
-               found = true;
-               break;
-       }
-       if (!found) {
-               /* Create */
-               e = alloc_dl_node(bin_data);
-               if (!e)
-                       return NULL;
-               cds_hlist_add_head(&e->node, head);
-       }
-       return e;
-}
-
-static
-void remove_dl_node(struct lttng_ust_dl_node *e)
-{
-       cds_hlist_del(&e->node);
-}
-
-/*
- * Trace statedump event into all sessions owned by the caller thread
- * for which statedump is pending.
- */
-static
-void trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
-{
-       struct cds_list_head *sessionsp;
-       struct lttng_ust_session_private *session_priv;
-
-       sessionsp = lttng_get_sessions();
-       cds_list_for_each_entry(session_priv, sessionsp, node) {
-               if (session_priv->owner != owner)
-                       continue;
-               if (!session_priv->statedump_pending)
-                       continue;
-               tp_cb(session_priv->pub, priv);
-       }
-}
-
-static
-void trace_bin_info_cb(struct lttng_ust_session *session, void *priv)
-{
-       struct bin_info_data *bin_data = (struct bin_info_data *) priv;
-
-       tracepoint(lttng_ust_statedump, bin_info,
-               session, bin_data->base_addr_ptr,
-               bin_data->resolved_path, bin_data->memsz,
-               bin_data->is_pic, bin_data->has_build_id,
-               bin_data->has_debug_link);
-}
-
-static
-void trace_build_id_cb(struct lttng_ust_session *session, void *priv)
-{
-       struct bin_info_data *bin_data = (struct bin_info_data *) priv;
-
-       tracepoint(lttng_ust_statedump, build_id,
-               session, bin_data->base_addr_ptr,
-               bin_data->build_id, bin_data->build_id_len);
-}
-
-static
-void trace_debug_link_cb(struct lttng_ust_session *session, void *priv)
-{
-       struct bin_info_data *bin_data = (struct bin_info_data *) priv;
-
-       tracepoint(lttng_ust_statedump, debug_link,
-               session, bin_data->base_addr_ptr,
-               bin_data->dbg_file, bin_data->crc);
-}
-
-static
-void procname_cb(struct lttng_ust_session *session, void *priv)
-{
-       char *procname = (char *) priv;
-       tracepoint(lttng_ust_statedump, procname, session, procname);
-}
-
-static
-void trace_start_cb(struct lttng_ust_session *session, void *priv)
-{
-       tracepoint(lttng_ust_statedump, start, session);
-}
-
-static
-void trace_end_cb(struct lttng_ust_session *session, void *priv)
-{
-       tracepoint(lttng_ust_statedump, end, session);
-}
-
-static
-int get_elf_info(struct bin_info_data *bin_data)
-{
-       struct lttng_ust_elf *elf;
-       int ret = 0, found;
-
-       elf = lttng_ust_elf_create(bin_data->resolved_path);
-       if (!elf) {
-               ret = -1;
-               goto end;
-       }
-
-       ret = lttng_ust_elf_get_memsz(elf, &bin_data->memsz);
-       if (ret) {
-               goto end;
-       }
-
-       found = 0;
-       ret = lttng_ust_elf_get_build_id(elf, &bin_data->build_id,
-                                       &bin_data->build_id_len,
-                                       &found);
-       if (ret) {
-               goto end;
-       }
-       bin_data->has_build_id = !!found;
-       found = 0;
-       ret = lttng_ust_elf_get_debug_link(elf, &bin_data->dbg_file,
-                                       &bin_data->crc,
-                                       &found);
-       if (ret) {
-               goto end;
-       }
-       bin_data->has_debug_link = !!found;
-
-       bin_data->is_pic = lttng_ust_elf_is_pic(elf);
-
-end:
-       lttng_ust_elf_destroy(elf);
-       return ret;
-}
-
-static
-void trace_baddr(struct bin_info_data *bin_data, void *owner)
-{
-       trace_statedump_event(trace_bin_info_cb, owner, bin_data);
-
-       if (bin_data->has_build_id)
-               trace_statedump_event(trace_build_id_cb, owner, bin_data);
-
-       if (bin_data->has_debug_link)
-               trace_statedump_event(trace_debug_link_cb, owner, bin_data);
-}
-
-static
-int extract_baddr(struct bin_info_data *bin_data)
-{
-       int ret = 0;
-       struct lttng_ust_dl_node *e;
-
-       if (!bin_data->vdso) {
-               ret = get_elf_info(bin_data);
-               if (ret) {
-                       goto end;
-               }
-       } else {
-               bin_data->memsz = 0;
-               bin_data->has_build_id = 0;
-               bin_data->has_debug_link = 0;
-       }
-
-       e = find_or_create_dl_node(bin_data);
-       if (!e) {
-               ret = -1;
-               goto end;
-       }
-       e->marked = true;
-end:
-       free(bin_data->build_id);
-       bin_data->build_id = NULL;
-       free(bin_data->dbg_file);
-       bin_data->dbg_file = NULL;
-       return ret;
-}
-
-static
-void trace_statedump_start(void *owner)
-{
-       trace_statedump_event(trace_start_cb, owner, NULL);
-}
-
-static
-void trace_statedump_end(void *owner)
-{
-       trace_statedump_event(trace_end_cb, owner, NULL);
-}
-
-static
-void iter_begin(struct dl_iterate_data *data)
-{
-       unsigned int i;
-
-       /*
-        * UST lock nests within dynamic loader lock.
-        *
-        * Hold this lock across handling of the module listing to
-        * protect memory allocation at early process start, due to
-        * interactions with libc-wrapper lttng malloc instrumentation.
-        */
-       if (ust_lock()) {
-               data->cancel = true;
-               return;
-       }
-
-       /* Ensure all entries are unmarked. */
-       for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
-               struct cds_hlist_head *head;
-               struct lttng_ust_dl_node *e;
-
-               head = &dl_state_table[i];
-               cds_hlist_for_each_entry_2(e, head, node)
-                       assert(!e->marked);
-       }
-}
-
-static
-void trace_lib_load(const struct bin_info_data *bin_data, void *ip)
-{
-       tracepoint(lttng_ust_lib, load,
-               ip, bin_data->base_addr_ptr, bin_data->resolved_path,
-               bin_data->memsz, bin_data->has_build_id,
-               bin_data->has_debug_link);
-
-       if (bin_data->has_build_id) {
-               tracepoint(lttng_ust_lib, build_id,
-                       ip, bin_data->base_addr_ptr, bin_data->build_id,
-                       bin_data->build_id_len);
-       }
-
-       if (bin_data->has_debug_link) {
-               tracepoint(lttng_ust_lib, debug_link,
-                       ip, bin_data->base_addr_ptr, bin_data->dbg_file,
-                       bin_data->crc);
-       }
-}
-
-static
-void trace_lib_unload(const struct bin_info_data *bin_data, void *ip)
-{
-       tracepoint(lttng_ust_lib, unload, ip, bin_data->base_addr_ptr);
-}
-
-static
-void iter_end(struct dl_iterate_data *data, void *ip)
-{
-       unsigned int i;
-
-       if (data->cancel)
-               goto end;
-       /*
-        * Iterate on hash table.
-        * For each marked, traced, do nothing.
-        * For each marked, not traced, trace lib open event. traced = true.
-        * For each unmarked, traced, trace lib close event. remove node.
-        * For each unmarked, not traced, remove node.
-        */
-       for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
-               struct cds_hlist_head *head;
-               struct lttng_ust_dl_node *e;
-
-               head = &dl_state_table[i];
-               cds_hlist_for_each_entry_2(e, head, node) {
-                       if (e->marked) {
-                               if (!e->traced) {
-                                       trace_lib_load(&e->bin_data, ip);
-                                       e->traced = true;
-                               }
-                               e->marked = false;
-                       } else {
-                               if (e->traced)
-                                       trace_lib_unload(&e->bin_data, ip);
-                               remove_dl_node(e);
-                               free_dl_node(e);
-                       }
-               }
-       }
-end:
-       ust_unlock();
-}
-
-static
-int extract_bin_info_events(struct dl_phdr_info *info, size_t size, void *_data)
-{
-       int j, ret = 0;
-       struct dl_iterate_data *data = _data;
-
-       if (data->first) {
-               iter_begin(data);
-               data->first = false;
-       }
-
-       if (data->cancel)
-               goto end;
-
-       for (j = 0; j < info->dlpi_phnum; j++) {
-               struct bin_info_data bin_data;
-
-               if (info->dlpi_phdr[j].p_type != PT_LOAD)
-                       continue;
-
-               memset(&bin_data, 0, sizeof(bin_data));
-
-               /* Calculate virtual memory address of the loadable segment */
-               bin_data.base_addr_ptr = (void *) info->dlpi_addr +
-                       info->dlpi_phdr[j].p_vaddr;
-
-               if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
-                       /*
-                        * Only the first phdr without a dlpi_name
-                        * encountered is considered as the program
-                        * executable. The rest are vdsos.
-                        */
-                       if (!data->exec_found) {
-                               ssize_t path_len;
-                               data->exec_found = 1;
-
-                               /*
-                                * Use /proc/self/exe to resolve the
-                                * executable's full path.
-                                */
-                               path_len = readlink("/proc/self/exe",
-                                                   bin_data.resolved_path,
-                                                   PATH_MAX - 1);
-                               if (path_len <= 0)
-                                       break;
-
-                               bin_data.resolved_path[path_len] = '\0';
-                               bin_data.vdso = 0;
-                       } else {
-                               snprintf(bin_data.resolved_path,
-                                       PATH_MAX - 1, "[vdso]");
-                               bin_data.vdso = 1;
-                       }
-               } else {
-                       /*
-                        * For regular dl_phdr_info entries check if
-                        * the path to the binary really exists. If not,
-                        * treat as vdso and use dlpi_name as 'path'.
-                        */
-                       if (!realpath(info->dlpi_name,
-                                       bin_data.resolved_path)) {
-                               snprintf(bin_data.resolved_path,
-                                       PATH_MAX - 1, "[%s]",
-                                       info->dlpi_name);
-                               bin_data.vdso = 1;
-                       } else {
-                               bin_data.vdso = 0;
-                       }
-               }
-
-               ret = extract_baddr(&bin_data);
-               break;
-       }
-end:
-       return ret;
-}
-
-static
-void ust_dl_table_statedump(void *owner)
-{
-       unsigned int i;
-
-       if (ust_lock())
-               goto end;
-
-       /* Statedump each traced table entry into session for owner. */
-       for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
-               struct cds_hlist_head *head;
-               struct lttng_ust_dl_node *e;
-
-               head = &dl_state_table[i];
-               cds_hlist_for_each_entry_2(e, head, node) {
-                       if (e->traced)
-                               trace_baddr(&e->bin_data, owner);
-               }
-       }
-
-end:
-       ust_unlock();
-}
-
-void lttng_ust_dl_update(void *ip)
-{
-       struct dl_iterate_data data;
-
-       if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
-               return;
-
-       /*
-        * Fixup lttng-ust TLS when called from dlopen/dlclose
-        * instrumentation.
-        */
-       lttng_ust_fixup_tls();
-
-       data.exec_found = 0;
-       data.first = true;
-       data.cancel = false;
-       /*
-        * Iterate through the list of currently loaded shared objects and
-        * generate tables entries for loadable segments using
-        * extract_bin_info_events.
-        * Removed libraries are detected by mark-and-sweep: marking is
-        * done in the iteration over libraries, and sweeping is
-        * performed by iter_end().
-        */
-       dl_iterate_phdr(extract_bin_info_events, &data);
-       if (data.first)
-               iter_begin(&data);
-       iter_end(&data, ip);
-}
-
-/*
- * Generate a statedump of base addresses of all shared objects loaded
- * by the traced application, as well as for the application's
- * executable itself.
- */
-static
-int do_baddr_statedump(void *owner)
-{
-       if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
-               return 0;
-       lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
-       ust_dl_table_statedump(owner);
-       return 0;
-}
-
-static
-int do_procname_statedump(void *owner)
-{
-       if (lttng_ust_getenv("LTTNG_UST_WITHOUT_PROCNAME_STATEDUMP"))
-               return 0;
-
-       trace_statedump_event(procname_cb, owner, lttng_ust_sockinfo_get_procname(owner));
-       return 0;
-}
-
-/*
- * Generate a statedump of a given traced application. A statedump is
- * delimited by start and end events. For a given (process, session)
- * pair, begin/end events are serialized and will match. However, in a
- * session, statedumps from different processes may be
- * interleaved. The vpid context should be used to identify which
- * events belong to which process.
- *
- * Grab the ust_lock outside of the RCU read-side lock because we
- * perform synchronize_rcu with the ust_lock held, which can trigger
- * deadlocks otherwise.
- */
-int do_lttng_ust_statedump(void *owner)
-{
-       ust_lock_nocheck();
-       trace_statedump_start(owner);
-       ust_unlock();
-
-       do_procname_statedump(owner);
-       do_baddr_statedump(owner);
-
-       ust_lock_nocheck();
-       trace_statedump_end(owner);
-       ust_unlock();
-
-       return 0;
-}
-
-void lttng_ust_statedump_init(void)
-{
-       __tracepoints__init();
-       __tracepoints__ptrs_init();
-       __lttng_events_init__lttng_ust_statedump();
-       lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
-}
-
-static
-void ust_dl_state_destroy(void)
-{
-       unsigned int i;
-
-       for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
-               struct cds_hlist_head *head;
-               struct lttng_ust_dl_node *e, *tmp;
-
-               head = &dl_state_table[i];
-               cds_hlist_for_each_entry_safe_2(e, tmp, head, node)
-                       free_dl_node(e);
-               CDS_INIT_HLIST_HEAD(head);
-       }
-}
-
-void lttng_ust_statedump_destroy(void)
-{
-       __lttng_events_exit__lttng_ust_statedump();
-       __tracepoints__ptrs_destroy();
-       __tracepoints__destroy();
-       ust_dl_state_destroy();
-}
This page took 0.02944 seconds and 4 git commands to generate.