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