1288957Sbdrewery/*- 2288957Sbdrewery * Copyright (c) 1988, 1993 3288957Sbdrewery * The Regents of the University of California. All rights reserved. 4288957Sbdrewery * 5288957Sbdrewery * Redistribution and use in source and binary forms, with or without 6288957Sbdrewery * modification, are permitted provided that the following conditions 7288957Sbdrewery * are met: 8288957Sbdrewery * 1. Redistributions of source code must retain the above copyright 9288957Sbdrewery * notice, this list of conditions and the following disclaimer. 10288957Sbdrewery * 2. Redistributions in binary form must reproduce the above copyright 11288957Sbdrewery * notice, this list of conditions and the following disclaimer in the 12288957Sbdrewery * documentation and/or other materials provided with the distribution. 13288957Sbdrewery * 4. Neither the name of the University nor the names of its contributors 14288957Sbdrewery * may be used to endorse or promote products derived from this software 15288957Sbdrewery * without specific prior written permission. 16288957Sbdrewery * 17288957Sbdrewery * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18288957Sbdrewery * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19288957Sbdrewery * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20288957Sbdrewery * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21288957Sbdrewery * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22288957Sbdrewery * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23288957Sbdrewery * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24288957Sbdrewery * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25288957Sbdrewery * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26288957Sbdrewery * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27288957Sbdrewery * SUCH DAMAGE. 28288957Sbdrewery */ 29288957Sbdrewery 30288957Sbdrewery#include <sys/cdefs.h> 31288957Sbdrewery__FBSDID("$FreeBSD: stable/11/lib/libsysdecode/utrace.c 311999 2017-01-12 22:06:57Z jhb $"); 32288957Sbdrewery 33288957Sbdrewery#include <sys/param.h> 34288957Sbdrewery#include <dlfcn.h> 35311999Sjhb#include <stdbool.h> 36288957Sbdrewery#include <stdio.h> 37304450Skib#include <string.h> 38292236Sjhb#include <sysdecode.h> 39304453Skib#include "rtld_utrace.h" 40288957Sbdrewery 41304450Skib#ifdef __LP64__ 42304450Skibstruct utrace_rtld32 { 43304453Skib char sig[4]; 44304450Skib int event; 45304450Skib uint32_t handle; 46304450Skib uint32_t mapbase; 47304450Skib uint32_t mapsize; 48304450Skib int refcnt; 49304450Skib char name[MAXPATHLEN]; 50304450Skib}; 51304450Skib#endif 52304450Skib 53292236Sjhbstatic int 54292236Sjhbprint_utrace_rtld(FILE *fp, void *p) 55288957Sbdrewery{ 56288957Sbdrewery struct utrace_rtld *ut = p; 57288957Sbdrewery void *parent; 58288957Sbdrewery int mode; 59288957Sbdrewery 60288957Sbdrewery switch (ut->event) { 61288957Sbdrewery case UTRACE_DLOPEN_START: 62288957Sbdrewery mode = ut->refcnt; 63288957Sbdrewery fprintf(fp, "dlopen(%s, ", ut->name); 64288957Sbdrewery switch (mode & RTLD_MODEMASK) { 65288957Sbdrewery case RTLD_NOW: 66288957Sbdrewery fprintf(fp, "RTLD_NOW"); 67288957Sbdrewery break; 68288957Sbdrewery case RTLD_LAZY: 69288957Sbdrewery fprintf(fp, "RTLD_LAZY"); 70288957Sbdrewery break; 71288957Sbdrewery default: 72288957Sbdrewery fprintf(fp, "%#x", mode & RTLD_MODEMASK); 73288957Sbdrewery } 74288957Sbdrewery if (mode & RTLD_GLOBAL) 75288957Sbdrewery fprintf(fp, " | RTLD_GLOBAL"); 76288957Sbdrewery if (mode & RTLD_TRACE) 77288957Sbdrewery fprintf(fp, " | RTLD_TRACE"); 78288957Sbdrewery if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)) 79288957Sbdrewery fprintf(fp, " | %#x", mode & 80288957Sbdrewery ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)); 81288957Sbdrewery fprintf(fp, ")"); 82288957Sbdrewery break; 83288957Sbdrewery case UTRACE_DLOPEN_STOP: 84288957Sbdrewery fprintf(fp, "%p = dlopen(%s) ref %d", ut->handle, ut->name, 85288957Sbdrewery ut->refcnt); 86288957Sbdrewery break; 87288957Sbdrewery case UTRACE_DLCLOSE_START: 88288957Sbdrewery fprintf(fp, "dlclose(%p) (%s, %d)", ut->handle, ut->name, 89288957Sbdrewery ut->refcnt); 90288957Sbdrewery break; 91288957Sbdrewery case UTRACE_DLCLOSE_STOP: 92288957Sbdrewery fprintf(fp, "dlclose(%p) finished", ut->handle); 93288957Sbdrewery break; 94288957Sbdrewery case UTRACE_LOAD_OBJECT: 95288957Sbdrewery fprintf(fp, "RTLD: loaded %p @ %p - %p (%s)", ut->handle, 96288957Sbdrewery ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 97288957Sbdrewery ut->name); 98288957Sbdrewery break; 99288957Sbdrewery case UTRACE_UNLOAD_OBJECT: 100288957Sbdrewery fprintf(fp, "RTLD: unloaded %p @ %p - %p (%s)", ut->handle, 101288957Sbdrewery ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, 102288957Sbdrewery ut->name); 103288957Sbdrewery break; 104288957Sbdrewery case UTRACE_ADD_RUNDEP: 105288957Sbdrewery parent = ut->mapbase; 106288957Sbdrewery fprintf(fp, "RTLD: %p now depends on %p (%s, %d)", parent, 107288957Sbdrewery ut->handle, ut->name, ut->refcnt); 108288957Sbdrewery break; 109288957Sbdrewery case UTRACE_PRELOAD_FINISHED: 110288957Sbdrewery fprintf(fp, "RTLD: LD_PRELOAD finished"); 111288957Sbdrewery break; 112288957Sbdrewery case UTRACE_INIT_CALL: 113288957Sbdrewery fprintf(fp, "RTLD: init %p for %p (%s)", ut->mapbase, ut->handle, 114288957Sbdrewery ut->name); 115288957Sbdrewery break; 116288957Sbdrewery case UTRACE_FINI_CALL: 117288957Sbdrewery fprintf(fp, "RTLD: fini %p for %p (%s)", ut->mapbase, ut->handle, 118288957Sbdrewery ut->name); 119288957Sbdrewery break; 120288957Sbdrewery case UTRACE_DLSYM_START: 121288957Sbdrewery fprintf(fp, "RTLD: dlsym(%p, %s)", ut->handle, ut->name); 122288957Sbdrewery break; 123288957Sbdrewery case UTRACE_DLSYM_STOP: 124288957Sbdrewery fprintf(fp, "RTLD: %p = dlsym(%p, %s)", ut->mapbase, ut->handle, 125288957Sbdrewery ut->name); 126288957Sbdrewery break; 127288957Sbdrewery default: 128292236Sjhb return (0); 129288957Sbdrewery } 130292236Sjhb return (1); 131288957Sbdrewery} 132288957Sbdrewery 133288957Sbdrewerystruct utrace_malloc { 134288957Sbdrewery void *p; 135288957Sbdrewery size_t s; 136288957Sbdrewery void *r; 137288957Sbdrewery}; 138288957Sbdrewery 139304450Skib#ifdef __LP64__ 140304450Skibstruct utrace_malloc32 { 141304450Skib uint32_t p; 142304450Skib uint32_t s; 143304450Skib uint32_t r; 144304450Skib}; 145304450Skib#endif 146304450Skib 147288957Sbdrewerystatic void 148288957Sbdreweryprint_utrace_malloc(FILE *fp, void *p) 149288957Sbdrewery{ 150288957Sbdrewery struct utrace_malloc *ut = p; 151288957Sbdrewery 152288957Sbdrewery if (ut->p == (void *)(intptr_t)(-1)) 153288957Sbdrewery fprintf(fp, "malloc_init()"); 154288957Sbdrewery else if (ut->s == 0) 155288957Sbdrewery fprintf(fp, "free(%p)", ut->p); 156288957Sbdrewery else if (ut->p == NULL) 157288957Sbdrewery fprintf(fp, "%p = malloc(%zu)", ut->r, ut->s); 158288957Sbdrewery else 159288957Sbdrewery fprintf(fp, "%p = realloc(%p, %zu)", ut->r, ut->p, ut->s); 160288957Sbdrewery} 161288957Sbdrewery 162288957Sbdreweryint 163292236Sjhbsysdecode_utrace(FILE *fp, void *p, size_t len) 164288957Sbdrewery{ 165304450Skib#ifdef __LP64__ 166304450Skib struct utrace_rtld ur; 167304450Skib struct utrace_rtld32 *pr; 168304450Skib struct utrace_malloc um; 169304450Skib struct utrace_malloc32 *pm; 170304450Skib#endif 171304453Skib static const char rtld_utrace_sig[RTLD_UTRACE_SIG_SZ] = RTLD_UTRACE_SIG; 172288957Sbdrewery 173304453Skib if (len == sizeof(struct utrace_rtld) && bcmp(p, rtld_utrace_sig, 174304453Skib sizeof(rtld_utrace_sig)) == 0) 175292236Sjhb return (print_utrace_rtld(fp, p)); 176288957Sbdrewery 177288957Sbdrewery if (len == sizeof(struct utrace_malloc)) { 178288957Sbdrewery print_utrace_malloc(fp, p); 179288957Sbdrewery return (1); 180288957Sbdrewery } 181304450Skib 182304450Skib#ifdef __LP64__ 183304453Skib if (len == sizeof(struct utrace_rtld32) && bcmp(p, rtld_utrace_sig, 184304453Skib sizeof(rtld_utrace_sig)) == 0) { 185304450Skib pr = p; 186304450Skib memset(&ur, 0, sizeof(ur)); 187304450Skib memcpy(ur.sig, pr->sig, sizeof(ur.sig)); 188304450Skib ur.event = pr->event; 189304450Skib ur.handle = (void *)(uintptr_t)pr->handle; 190304450Skib ur.mapbase = (void *)(uintptr_t)pr->mapbase; 191304450Skib ur.mapsize = pr->mapsize; 192304450Skib ur.refcnt = pr->refcnt; 193304450Skib memcpy(ur.name, pr->name, sizeof(ur.name)); 194304450Skib return (print_utrace_rtld(fp, &ur)); 195304450Skib } 196304450Skib 197304450Skib if (len == sizeof(struct utrace_malloc32)) { 198304450Skib pm = p; 199304450Skib memset(&um, 0, sizeof(um)); 200304450Skib um.p = pm->p == (uint32_t)-1 ? (void *)(intptr_t)-1 : 201304450Skib (void *)(uintptr_t)pm->p; 202304450Skib um.s = pm->s; 203304450Skib um.r = (void *)(uintptr_t)pm->r; 204304450Skib print_utrace_malloc(fp, &um); 205304450Skib return (1); 206304450Skib } 207304450Skib#endif 208304450Skib 209288957Sbdrewery return (0); 210288957Sbdrewery} 211