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