summaryrefslogtreecommitdiff
path: root/libexec/ld.so/alpha
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-06-01 09:57:59 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-06-01 09:57:59 +0000
commit68aee1affc9e9f623b3824770f05f34d7c2fe60a (patch)
treeff6bb4ec4eab9b40d691aebff013e69dbf58683a /libexec/ld.so/alpha
parentef21a2cb5b0d81e925c90a50449ba06a311298e0 (diff)
Introduce ltrace(1). This tool works with ld.so to inject utrace record for
each plt call, allowing to trace a binary linked against shared library at the public function call level. To do so, ltrace(1) sets up some environment variables to enable plt tracing in ld.so, and invokes ktrace(2) for utrace events. ld.so will force lazy binding and will send an utrace record in the plt resolver, without updating the plt. Minimal filtering capabilities are provided, inspired by Solaris' truss -u, to limit tracing to libraries and/or symbol names. Non-traced libraries and symbols will have the regular resolver processing, with the expected plt update. "Get it in" deraadt
Diffstat (limited to 'libexec/ld.so/alpha')
-rw-r--r--libexec/ld.so/alpha/ldasm.S7
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c13
-rw-r--r--libexec/ld.so/alpha/syscall.h3
3 files changed, 17 insertions, 6 deletions
diff --git a/libexec/ld.so/alpha/ldasm.S b/libexec/ld.so/alpha/ldasm.S
index 6264cd5f7f1..5fb82ed6d0c 100644
--- a/libexec/ld.so/alpha/ldasm.S
+++ b/libexec/ld.so/alpha/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.19 2013/04/05 12:58:03 kurt Exp $ */
+/* $OpenBSD: ldasm.S,v 1.20 2013/06/01 09:57:57 miod Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -325,3 +325,8 @@ LEAF_NOPROFILE(_dl_getcwd, 2)
RET
END(_dl_getcwd)
+LEAF_NOPROFILE(_dl_utrace, 2)
+ ldiq v0, SYS_utrace
+ call_pal PAL_OSF1_callsys
+ RET
+END(_dl_utrace)
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c
index 37480b01f54..5fa6273707d 100644
--- a/libexec/ld.so/alpha/rtld_machine.c
+++ b/libexec/ld.so/alpha/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.48 2013/05/08 20:55:14 guenther Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.49 2013/06/01 09:57:57 miod Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -208,6 +208,7 @@ _dl_bind(elf_object_t *object, int reloff)
Elf_Addr *addr, ooff;
const Elf_Sym *sym, *this;
const char *symn;
+ const elf_object_t *sobj;
sigset_t savedmask;
rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
@@ -229,13 +230,15 @@ _dl_bind(elf_object_t *object, int reloff)
this = NULL;
ooff = _dl_find_symbol(symn, &this,
- SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym,
- object, NULL);
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, object, &sobj);
if (this == NULL) {
_dl_printf("lazy binding failed!\n");
*((int *)0) = 0; /* XXX */
}
+ if (sobj->traced && _dl_trace_plt(sobj, symn))
+ return ooff + this->st_value + rela->r_addend;
+
/* if PLT is protected, allow the write */
if (object->plt_size != 0) {
_dl_thread_bind_lock(0, &savedmask);
@@ -268,7 +271,6 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
Elf_Addr plt_addr;
const Elf_Sym *this;
-
pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
object->got_addr = 0;
@@ -314,6 +316,9 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz);
}
+ if (object->traced)
+ lazy = 1;
+
if (object->obj_type == OBJTYPE_LDR || !lazy || pltgot == NULL) {
fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
} else {
diff --git a/libexec/ld.so/alpha/syscall.h b/libexec/ld.so/alpha/syscall.h
index c5d48531659..d4c58fd98f0 100644
--- a/libexec/ld.so/alpha/syscall.h
+++ b/libexec/ld.so/alpha/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.19 2013/04/05 12:58:03 kurt Exp $ */
+/* $OpenBSD: syscall.h,v 1.20 2013/06/01 09:57:57 miod Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -56,6 +56,7 @@ int _dl_gettimeofday(struct timeval *tp, struct timezone *tzp);
int _dl_readlink(const char *path, char *buf, size_t bufsiz);
int _dl_lstat(const char *path, struct stat *sb);
int _dl_getcwd(char *buf, size_t size);
+int _dl_utrace(const char *label, const void *addr, size_t len);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)