summaryrefslogtreecommitdiff
path: root/libexec/ld.so/ldd
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2015-01-20 02:16:20 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2015-01-20 02:16:20 +0000
commit905ed6512d113cd69dd3ae060547ac92ad12ba06 (patch)
tree013641677b90ceae84aa6c382494a1817a092400 /libexec/ld.so/ldd
parent25ce9a50811f15a7fa1166f22cbb1247d4181b56 (diff)
Add support for tracing libraries in static PIE binaries. rcrt does not
contain "LD_TRACE_LOADED_OBJECTS" support, so this gets done by calling RTLD_TRACE directly. ok guenther
Diffstat (limited to 'libexec/ld.so/ldd')
-rw-r--r--libexec/ld.so/ldd/ldd.c59
1 files changed, 39 insertions, 20 deletions
diff --git a/libexec/ld.so/ldd/ldd.c b/libexec/ld.so/ldd/ldd.c
index 127961be189..c1488cbf45a 100644
--- a/libexec/ld.so/ldd/ldd.c
+++ b/libexec/ld.so/ldd/ldd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldd.c,v 1.18 2015/01/16 16:18:07 deraadt Exp $ */
+/* $OpenBSD: ldd.c,v 1.19 2015/01/20 02:16:19 deraadt Exp $ */
/*
* Copyright (c) 2001 Artur Grabowski <art@openbsd.org>
* All rights reserved.
@@ -30,9 +30,11 @@
#include <err.h>
#include <fcntl.h>
#include <string.h>
+#include <signal.h>
#include <unistd.h>
#include <limits.h>
#include <dlfcn.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/mman.h>
@@ -96,6 +98,7 @@ doit(char *name)
Elf_Phdr *phdr;
int fd, i, size, status, interp=0;
char buf[PATH_MAX];
+ struct stat st;
void * dlhandle;
if ((fd = open(name, O_RDONLY)) < 0) {
@@ -103,6 +106,17 @@ doit(char *name)
return 1;
}
+ if (fstat(fd, &st) == -1) {
+ warn("%s", name);
+ close(fd);
+ return 1;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ warnx("%s: not an regular file", name);
+ close(fd);
+ return 1;
+ }
if (read(fd, &ehdr, sizeof(ehdr)) < 0) {
warn("read(%s)", name);
close(fd);
@@ -135,31 +149,34 @@ doit(char *name)
}
free(phdr);
- if (ehdr.e_type == ET_DYN && !interp) {
- printf("%s:\n", name);
- if (realpath(name, buf) == NULL) {
- warn("realpath(%s)", name);
- return 1;
- }
- dlhandle = dlopen(buf, RTLD_TRACE);
- if (dlhandle == NULL) {
- printf("%s\n", dlerror());
- return 1;
- }
- return 0;
- }
-
- if (i == ehdr.e_phnum) {
- warnx("%s: not a dynamic executable", name);
- return 1;
- }
-
printf("%s:\n", name);
fflush(stdout);
switch (fork()) {
case -1:
err(1, "fork");
case 0:
+ if (ehdr.e_type == ET_DYN && !interp) {
+ if (realpath(name, buf) == NULL) {
+ printf("realpath(%s): %s", name,
+ strerror(errno));
+ fflush(stdout);
+ _exit(1);
+ }
+ dlhandle = dlopen(buf, RTLD_TRACE);
+ if (dlhandle == NULL) {
+ printf("%s\n", dlerror());
+ fflush(stdout);
+ _exit(1);
+ }
+ _exit(0);
+ }
+
+ if (i == ehdr.e_phnum) {
+ printf("not a dynamic executable\n");
+ fflush(stdout);
+ _exit(0);
+ }
+
execl(name, name, (char *)NULL);
perror(name);
_exit(1);
@@ -169,6 +186,8 @@ doit(char *name)
return 1;
}
if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) == SIGINT)
+ return 1;
fprintf(stderr, "%s: signal %d\n", name,
WTERMSIG(status));
return 1;