aboutsummaryrefslogtreecommitdiff
path: root/elf/pldd.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/pldd.c')
-rw-r--r--elf/pldd.c344
1 files changed, 0 insertions, 344 deletions
diff --git a/elf/pldd.c b/elf/pldd.c
deleted file mode 100644
index ddfa88d63b..0000000000
--- a/elf/pldd.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/* List dynamic shared objects linked into given process.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <alloca.h>
-#include <argp.h>
-#include <assert.h>
-#include <dirent.h>
-#include <elf.h>
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <libintl.h>
-#include <link.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ptrace.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <scratch_buffer.h>
-
-#include <ldsodefs.h>
-#include <version.h>
-
-/* Global variables. */
-extern char *program_invocation_short_name;
-#define PACKAGE _libc_intl_domainname
-
-/* External functions. */
-#include <programs/xmalloc.h>
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("\
-List dynamic shared objects loaded into process.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("PID");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help, NULL
-};
-
-// File descriptor of /proc/*/mem file.
-static int memfd;
-
-/* Name of the executable */
-static char *exe;
-
-/* Local functions. */
-static int get_process_info (int dfd, long int pid);
-static void wait_for_ptrace_stop (long int pid);
-
-
-int
-main (int argc, char *argv[])
-{
- /* Parse and process arguments. */
- int remaining;
- argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- if (remaining != argc - 1)
- {
- fprintf (stderr,
- gettext ("Exactly one parameter with process ID required.\n"));
- argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
- return 1;
- }
-
- assert (sizeof (pid_t) == sizeof (int)
- || sizeof (pid_t) == sizeof (long int));
- char *endp;
- errno = 0;
- long int pid = strtol (argv[remaining], &endp, 10);
- if (pid < 0 || (pid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
- || (sizeof (pid_t) < sizeof (pid) && pid > INT_MAX))
- error (EXIT_FAILURE, 0, gettext ("invalid process ID '%s'"),
- argv[remaining]);
-
- /* Determine the program name. */
- char buf[7 + 3 * sizeof (pid)];
- snprintf (buf, sizeof (buf), "/proc/%lu", pid);
- int dfd = open (buf, O_RDONLY | O_DIRECTORY);
- if (dfd == -1)
- error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
-
- struct scratch_buffer exebuf;
- scratch_buffer_init (&exebuf);
- ssize_t nexe;
- while ((nexe = readlinkat (dfd, "exe",
- exebuf.data, exebuf.length)) == exebuf.length)
- {
- if (!scratch_buffer_grow (&exebuf))
- {
- nexe = -1;
- break;
- }
- }
- if (nexe == -1)
- exe = (char *) "<program name undetermined>";
- else
- {
- exe = exebuf.data;
- exe[nexe] = '\0';
- }
-
- /* Stop all threads since otherwise the list of loaded modules might
- change while we are reading it. */
- struct thread_list
- {
- pid_t tid;
- struct thread_list *next;
- } *thread_list = NULL;
-
- int taskfd = openat (dfd, "task", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
- if (taskfd == 1)
- error (EXIT_FAILURE, errno, gettext ("cannot open %s/task"), buf);
- DIR *dir = fdopendir (taskfd);
- if (dir == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
- buf);
-
- struct dirent64 *d;
- while ((d = readdir64 (dir)) != NULL)
- {
- if (! isdigit (d->d_name[0]))
- continue;
-
- errno = 0;
- long int tid = strtol (d->d_name, &endp, 10);
- if (tid < 0 || (tid == ULONG_MAX && errno == ERANGE) || *endp != '\0'
- || (sizeof (pid_t) < sizeof (pid) && tid > INT_MAX))
- error (EXIT_FAILURE, 0, gettext ("invalid thread ID '%s'"),
- d->d_name);
-
- if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
- {
- /* There might be a race between reading the directory and
- threads terminating. Ignore errors attaching to unknown
- threads unless this is the main thread. */
- if (errno == ESRCH && tid != pid)
- continue;
-
- error (EXIT_FAILURE, errno, gettext ("cannot attach to process %lu"),
- tid);
- }
-
- wait_for_ptrace_stop (tid);
-
- struct thread_list *newp = alloca (sizeof (*newp));
- newp->tid = tid;
- newp->next = thread_list;
- thread_list = newp;
- }
-
- closedir (dir);
-
- int status = get_process_info (dfd, pid);
-
- assert (thread_list != NULL);
- do
- {
- ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
- thread_list = thread_list->next;
- }
- while (thread_list != NULL);
-
- close (dfd);
-
- return status;
-}
-
-
-/* Wait for PID to enter ptrace-stop state after being attached. */
-static void
-wait_for_ptrace_stop (long int pid)
-{
- int status;
-
- /* While waiting for SIGSTOP being delivered to the tracee we have to
- reinject any other pending signal. Ignore all other errors. */
- while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status))
- {
- /* The STOP signal should not be delivered to the tracee. */
- if (WSTOPSIG (status) == SIGSTOP)
- return;
- if (ptrace (PTRACE_CONT, pid, NULL,
- (void *) (uintptr_t) WSTOPSIG (status)))
- /* The only possible error is that the process died. */
- return;
- }
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-/* Print bug-reporting information in the help message. */
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *tp = NULL;
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&tp, gettext ("\
-For bug reporting instructions, please see:\n\
-%s.\n"), REPORT_BUGS_TO) < 0)
- return NULL;
- return tp;
- default:
- break;
- }
- return (char *) text;
-}
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "pldd %s%s\n", PKGVERSION, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2017");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-#define CLASS 32
-#include "pldd-xx.c"
-#define CLASS 64
-#include "pldd-xx.c"
-
-
-static int
-get_process_info (int dfd, long int pid)
-{
- memfd = openat (dfd, "mem", O_RDONLY);
- if (memfd == -1)
- goto no_info;
-
- int fd = openat (dfd, "exe", O_RDONLY);
- if (fd == -1)
- {
- no_info:
- error (0, errno, gettext ("cannot get information about process %lu"),
- pid);
- return EXIT_FAILURE;
- }
-
- char e_ident[EI_NIDENT];
- if (read (fd, e_ident, EI_NIDENT) != EI_NIDENT)
- goto no_info;
-
- close (fd);
-
- if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
- {
- error (0, 0, gettext ("process %lu is no ELF program"), pid);
- return EXIT_FAILURE;
- }
-
- fd = openat (dfd, "auxv", O_RDONLY);
- if (fd == -1)
- goto no_info;
-
- size_t auxv_size = 0;
- void *auxv = NULL;
- while (1)
- {
- auxv_size += 512;
- auxv = xrealloc (auxv, auxv_size);
-
- ssize_t n = pread (fd, auxv, auxv_size, 0);
- if (n < 0)
- goto no_info;
- if (n < auxv_size)
- {
- auxv_size = n;
- break;
- }
- }
-
- close (fd);
-
- int retval;
- if (e_ident[EI_CLASS] == ELFCLASS32)
- retval = find_maps32 (pid, auxv, auxv_size);
- else
- retval = find_maps64 (pid, auxv, auxv_size);
-
- free (auxv);
- close (memfd);
-
- return retval;
-}