kern_ctf.c revision 278984
1147072Sbrooks/*-
2147072Sbrooks * Copyright (c) 2008 John Birrell <jb@freebsd.org>
3147072Sbrooks * All rights reserved.
4147072Sbrooks *
5147072Sbrooks * Redistribution and use in source and binary forms, with or without
6147072Sbrooks * modification, are permitted provided that the following conditions
7147072Sbrooks * are met:
8147072Sbrooks * 1. Redistributions of source code must retain the above copyright
9147072Sbrooks *    notice, this list of conditions and the following disclaimer.
10147072Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
11147072Sbrooks *    notice, this list of conditions and the following disclaimer in the
12147072Sbrooks *    documentation and/or other materials provided with the distribution.
13147072Sbrooks *
14147072Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15147072Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16147072Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17147072Sbrooks * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18147072Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19147072Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20147072Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21147072Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22147072Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23147072Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24147072Sbrooks * SUCH DAMAGE.
25147072Sbrooks *
26147072Sbrooks * $FreeBSD: head/sys/kern/kern_ctf.c 278984 2015-02-19 03:32:48Z markj $
27147072Sbrooks */
28147072Sbrooks
29147072Sbrooks/*
30147072Sbrooks * Note this file is included by both link_elf.c and link_elf_obj.c.
31147072Sbrooks *
32147072Sbrooks * The CTF header structure definition can't be used here because it's
33147072Sbrooks * (annoyingly) covered by the CDDL. We will just use a few bytes from
34147072Sbrooks * it as an integer array where we 'know' what they mean.
35147072Sbrooks */
36147072Sbrooks#define CTF_HDR_SIZE		36
37147072Sbrooks#define CTF_HDR_STRTAB_U32	7
38147072Sbrooks#define CTF_HDR_STRLEN_U32	8
39147072Sbrooks
40147072Sbrooks#ifdef DDB_CTF
41147072Sbrooksstatic void *
42147072Sbrooksz_alloc(void *nil, u_int items, u_int size)
43149399Sbrooks{
44149399Sbrooks	void *ptr;
45149399Sbrooks
46147072Sbrooks	ptr = malloc(items * size, M_TEMP, M_NOWAIT);
47147072Sbrooks	return ptr;
48147072Sbrooks}
49147072Sbrooks
50147072Sbrooksstatic void
51147072Sbrooksz_free(void *nil, void *ptr)
52147072Sbrooks{
53147072Sbrooks	free(ptr, M_TEMP);
54147072Sbrooks}
55147072Sbrooks
56147072Sbrooks#endif
57147072Sbrooks
58147072Sbrooksstatic int
59147072Sbrookslink_elf_ctf_get(linker_file_t lf, linker_ctf_t *lc)
60147072Sbrooks{
61147072Sbrooks#ifdef DDB_CTF
62147072Sbrooks	Elf_Ehdr *hdr = NULL;
63147072Sbrooks	Elf_Shdr *shdr = NULL;
64147072Sbrooks	caddr_t ctftab = NULL;
65147072Sbrooks	caddr_t raw = NULL;
66147072Sbrooks	caddr_t shstrtab = NULL;
67147072Sbrooks	elf_file_t ef = (elf_file_t) lf;
68147072Sbrooks	int flags;
69147072Sbrooks	int i;
70147072Sbrooks	int nbytes;
71147072Sbrooks	ssize_t resid;
72147072Sbrooks	size_t sz;
73147072Sbrooks	struct nameidata nd;
74147072Sbrooks	struct thread *td = curthread;
75147072Sbrooks	uint8_t ctf_hdr[CTF_HDR_SIZE];
76147072Sbrooks#endif
77147072Sbrooks	int error = 0;
78147072Sbrooks
79147072Sbrooks	if (lf == NULL || lc == NULL)
80147072Sbrooks		return (EINVAL);
81147072Sbrooks
82147072Sbrooks	/* Set the defaults for no CTF present. That's not a crime! */
83147072Sbrooks	bzero(lc, sizeof(*lc));
84147072Sbrooks
85147072Sbrooks#ifdef DDB_CTF
86147072Sbrooks	/*
87147072Sbrooks	 * First check if we've tried to load CTF data previously and the
88147072Sbrooks	 * CTF ELF section wasn't found. We flag that condition by setting
89147072Sbrooks	 * ctfcnt to -1. See below.
90147072Sbrooks	 */
91147072Sbrooks	if (ef->ctfcnt < 0)
92147072Sbrooks		return (EFTYPE);
93147072Sbrooks
94147072Sbrooks	/* Now check if we've already loaded the CTF data.. */
95147072Sbrooks	if (ef->ctfcnt > 0) {
96147072Sbrooks		/* We only need to load once. */
97147072Sbrooks		lc->ctftab = ef->ctftab;
98147072Sbrooks		lc->ctfcnt = ef->ctfcnt;
99147072Sbrooks		lc->symtab = ef->ddbsymtab;
100147072Sbrooks		lc->strtab = ef->ddbstrtab;
101147072Sbrooks		lc->strcnt = ef->ddbstrcnt;
102147072Sbrooks		lc->nsym   = ef->ddbsymcnt;
103147072Sbrooks		lc->ctfoffp = (uint32_t **) &ef->ctfoff;
104147072Sbrooks		lc->typoffp = (uint32_t **) &ef->typoff;
105147072Sbrooks		lc->typlenp = &ef->typlen;
106147072Sbrooks		return (0);
107147072Sbrooks	}
108147072Sbrooks
109147072Sbrooks	/*
110147072Sbrooks	 * We need to try reading the CTF data. Flag no CTF data present
111147072Sbrooks	 * by default and if we actually succeed in reading it, we'll
112147072Sbrooks	 * update ctfcnt to the number of bytes read.
113147072Sbrooks	 */
114147072Sbrooks	ef->ctfcnt = -1;
115147072Sbrooks
116147072Sbrooks	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, lf->pathname, td);
117147072Sbrooks	flags = FREAD;
118147072Sbrooks	error = vn_open(&nd, &flags, 0, NULL);
119228614Sdim	if (error)
120147072Sbrooks		return (error);
121147072Sbrooks	NDFREE(&nd, NDF_ONLY_PNBUF);
122147072Sbrooks
123147072Sbrooks	/* Allocate memory for the FLF header. */
124147072Sbrooks	hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK);
125147072Sbrooks
126147072Sbrooks	/* Read the ELF header. */
127147072Sbrooks	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, hdr, sizeof(*hdr),
128228614Sdim	    0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid,
129228614Sdim	    td)) != 0)
130147072Sbrooks		goto out;
131147072Sbrooks
132228615Sdim	/* Sanity check. */
133147072Sbrooks	if (!IS_ELF(*hdr)) {
134147072Sbrooks		error = ENOEXEC;
135147072Sbrooks		goto out;
136147072Sbrooks	}
137147072Sbrooks
138147072Sbrooks	nbytes = hdr->e_shnum * hdr->e_shentsize;
139147072Sbrooks	if (nbytes == 0 || hdr->e_shoff == 0 ||
140147072Sbrooks	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
141147072Sbrooks		error = ENOEXEC;
142147072Sbrooks		goto out;
143147072Sbrooks	}
144147072Sbrooks
145147072Sbrooks	/* Allocate memory for all the section headers */
146147072Sbrooks	shdr = malloc(nbytes, M_LINKER, M_WAITOK);
147147072Sbrooks
148147072Sbrooks	/* Read all the section headers */
149147072Sbrooks	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes,
150147072Sbrooks	    hdr->e_shoff, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
151147072Sbrooks	    &resid, td)) != 0)
152147072Sbrooks		goto out;
153147072Sbrooks
154147072Sbrooks	/*
155147072Sbrooks	 * We need to search for the CTF section by name, so if the
156147072Sbrooks	 * section names aren't present, then we can't locate the
157147072Sbrooks	 * .SUNW_ctf section containing the CTF data.
158147072Sbrooks	 */
159147072Sbrooks	if (hdr->e_shstrndx == 0 || shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) {
160147072Sbrooks		printf("%s(%d): module %s e_shstrndx is %d, sh_type is %d\n",
161147072Sbrooks		    __func__, __LINE__, lf->pathname, hdr->e_shstrndx,
162147072Sbrooks		    shdr[hdr->e_shstrndx].sh_type);
163147072Sbrooks		error = EFTYPE;
164147072Sbrooks		goto out;
165147072Sbrooks	}
166147072Sbrooks
167147072Sbrooks	/* Allocate memory to buffer the section header strings. */
168147072Sbrooks	shstrtab = malloc(shdr[hdr->e_shstrndx].sh_size, M_LINKER, M_WAITOK);
169147072Sbrooks
170147072Sbrooks	/* Read the section header strings. */
171147072Sbrooks	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, shstrtab,
172147072Sbrooks	    shdr[hdr->e_shstrndx].sh_size, shdr[hdr->e_shstrndx].sh_offset,
173147072Sbrooks	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid,
174147072Sbrooks	    td)) != 0)
175147072Sbrooks		goto out;
176147072Sbrooks
177147072Sbrooks	/* Search for the section containing the CTF data. */
178147072Sbrooks	for (i = 0; i < hdr->e_shnum; i++)
179147072Sbrooks		if (strcmp(".SUNW_ctf", shstrtab + shdr[i].sh_name) == 0)
180147072Sbrooks			break;
181147072Sbrooks
182147072Sbrooks	/* Check if the CTF section wasn't found. */
183147072Sbrooks	if (i >= hdr->e_shnum) {
184147072Sbrooks		printf("%s(%d): module %s has no .SUNW_ctf section\n",
185147072Sbrooks		    __func__, __LINE__, lf->pathname);
186147072Sbrooks		error = EFTYPE;
187147072Sbrooks		goto out;
188147072Sbrooks	}
189147072Sbrooks
190147072Sbrooks	/* Read the CTF header. */
191147072Sbrooks	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, ctf_hdr, sizeof(ctf_hdr),
192147072Sbrooks	    shdr[i].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
193147072Sbrooks	    NOCRED, &resid, td)) != 0)
194147072Sbrooks		goto out;
195147072Sbrooks
196147072Sbrooks	/* Check the CTF magic number. (XXX check for big endian!) */
197147072Sbrooks	if (ctf_hdr[0] != 0xf1 || ctf_hdr[1] != 0xcf) {
198147072Sbrooks		printf("%s(%d): module %s has invalid format\n",
199147072Sbrooks		    __func__, __LINE__, lf->pathname);
200147072Sbrooks		error = EFTYPE;
201147072Sbrooks		goto out;
202147072Sbrooks	}
203147072Sbrooks
204147072Sbrooks	/* Check if version 2. */
205147072Sbrooks	if (ctf_hdr[2] != 2) {
206147072Sbrooks		printf("%s(%d): module %s CTF format version is %d "
207147072Sbrooks		    "(2 expected)\n",
208147072Sbrooks		    __func__, __LINE__, lf->pathname, ctf_hdr[2]);
209147072Sbrooks		error = EFTYPE;
210147072Sbrooks		goto out;
211147072Sbrooks	}
212147072Sbrooks
213147072Sbrooks	/* Check if the data is compressed. */
214147072Sbrooks	if ((ctf_hdr[3] & 0x1) != 0) {
215147072Sbrooks		uint32_t *u32 = (uint32_t *) ctf_hdr;
216147072Sbrooks
217147072Sbrooks		/*
218147072Sbrooks		 * The last two fields in the CTF header are the offset
219147072Sbrooks		 * from the end of the header to the start of the string
220147072Sbrooks		 * data and the length of that string data. se this
221147072Sbrooks		 * information to determine the decompressed CTF data
222147072Sbrooks		 * buffer required.
223147072Sbrooks		 */
224147072Sbrooks		sz = u32[CTF_HDR_STRTAB_U32] + u32[CTF_HDR_STRLEN_U32] +
225147072Sbrooks		    sizeof(ctf_hdr);
226147072Sbrooks
227147072Sbrooks		/*
228147072Sbrooks		 * Allocate memory for the compressed CTF data, including
229147072Sbrooks		 * the header (which isn't compressed).
230147072Sbrooks		 */
231147072Sbrooks		raw = malloc(shdr[i].sh_size, M_LINKER, M_WAITOK);
232147072Sbrooks	} else {
233147072Sbrooks		/*
234147072Sbrooks		 * The CTF data is not compressed, so the ELF section
235147072Sbrooks		 * size is the same as the buffer size required.
236147072Sbrooks		 */
237147072Sbrooks		sz = shdr[i].sh_size;
238147072Sbrooks	}
239147072Sbrooks
240147072Sbrooks	/*
241147072Sbrooks	 * Allocate memory to buffer the CTF data in it's decompressed
242147072Sbrooks	 * form.
243147072Sbrooks	 */
244147072Sbrooks	ctftab = malloc(sz, M_LINKER, M_WAITOK);
245147072Sbrooks
246147072Sbrooks	/*
247228614Sdim	 * Read the CTF data into the raw buffer if compressed, or
248147072Sbrooks	 * directly into the CTF buffer otherwise.
249147072Sbrooks	 */
250147072Sbrooks	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, raw == NULL ? ctftab : raw,
251147072Sbrooks	    shdr[i].sh_size, shdr[i].sh_offset, UIO_SYSSPACE, IO_NODELOCKED,
252147072Sbrooks	    td->td_ucred, NOCRED, &resid, td)) != 0)
253147072Sbrooks		goto out;
254147072Sbrooks
255147072Sbrooks	/* Check if decompression is required. */
256147072Sbrooks	if (raw != NULL) {
257147072Sbrooks		z_stream zs;
258147072Sbrooks		int ret;
259147072Sbrooks
260147072Sbrooks		/*
261147072Sbrooks		 * The header isn't compressed, so copy that into the
262147072Sbrooks		 * CTF buffer first.
263147072Sbrooks		 */
264147072Sbrooks		bcopy(ctf_hdr, ctftab, sizeof(ctf_hdr));
265147072Sbrooks
266147072Sbrooks		/* Initialise the zlib structure. */
267147072Sbrooks		bzero(&zs, sizeof(zs));
268147072Sbrooks		zs.zalloc = z_alloc;
269147072Sbrooks		zs.zfree = z_free;
270147072Sbrooks
271147072Sbrooks		if (inflateInit(&zs) != Z_OK) {
272147072Sbrooks			error = EIO;
273147072Sbrooks			goto out;
274147072Sbrooks		}
275147072Sbrooks
276147072Sbrooks		zs.avail_in = shdr[i].sh_size - sizeof(ctf_hdr);
277147072Sbrooks		zs.next_in = ((uint8_t *) raw) + sizeof(ctf_hdr);
278147072Sbrooks		zs.avail_out = sz - sizeof(ctf_hdr);
279147072Sbrooks		zs.next_out = ((uint8_t *) ctftab) + sizeof(ctf_hdr);
280147072Sbrooks		ret = inflate(&zs, Z_FINISH);
281147072Sbrooks		inflateEnd(&zs);
282147072Sbrooks		if (ret != Z_STREAM_END) {
283147072Sbrooks			printf("%s(%d): zlib inflate returned %d\n", __func__, __LINE__, ret);
284147072Sbrooks			error = EIO;
285147072Sbrooks			goto out;
286147072Sbrooks		}
287147072Sbrooks	}
288147072Sbrooks
289147072Sbrooks	/* Got the CTF data! */
290147072Sbrooks	ef->ctftab = ctftab;
291147072Sbrooks	ef->ctfcnt = shdr[i].sh_size;
292147072Sbrooks
293147072Sbrooks	/* We'll retain the memory allocated for the CTF data. */
294228614Sdim	ctftab = NULL;
295228614Sdim
296147072Sbrooks	/* Let the caller use the CTF data read. */
297147072Sbrooks	lc->ctftab = ef->ctftab;
298228615Sdim	lc->ctfcnt = ef->ctfcnt;
299147072Sbrooks	lc->symtab = ef->ddbsymtab;
300147072Sbrooks	lc->strtab = ef->ddbstrtab;
301147072Sbrooks	lc->strcnt = ef->ddbstrcnt;
302147072Sbrooks	lc->nsym   = ef->ddbsymcnt;
303147072Sbrooks	lc->ctfoffp = (uint32_t **) &ef->ctfoff;
304147072Sbrooks	lc->typoffp = (uint32_t **) &ef->typoff;
305147072Sbrooks	lc->typlenp = &ef->typlen;
306147072Sbrooks
307147072Sbrooksout:
308147072Sbrooks	VOP_UNLOCK(nd.ni_vp, 0);
309147072Sbrooks	vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
310147072Sbrooks
311147072Sbrooks	if (hdr != NULL)
312147072Sbrooks		free(hdr, M_LINKER);
313147072Sbrooks	if (shdr != NULL)
314147072Sbrooks		free(shdr, M_LINKER);
315147072Sbrooks	if (shstrtab != NULL)
316147072Sbrooks		free(shstrtab, M_LINKER);
317147072Sbrooks	if (ctftab != NULL)
318147072Sbrooks		free(ctftab, M_LINKER);
319147072Sbrooks	if (raw != NULL)
320147072Sbrooks		free(raw, M_LINKER);
321147072Sbrooks#else
322147072Sbrooks	error = EOPNOTSUPP;
323147072Sbrooks#endif
324147072Sbrooks
325147072Sbrooks	return (error);
326147072Sbrooks}
327147072Sbrooks