xref: /illumos-gate/usr/src/common/ctf/ctf_util.c (revision 88a08813)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
26bc1f688bSRobert Mustacchi /*
27bc1f688bSRobert Mustacchi  * Copyright (c) 2015, Joyent, Inc.
28bc1f688bSRobert Mustacchi  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <ctf_impl.h>
31bc1f688bSRobert Mustacchi #include <sys/debug.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Simple doubly-linked list append routine.  This implementation assumes that
357c478bd9Sstevel@tonic-gate  * each list element contains an embedded ctf_list_t as the first member.
367c478bd9Sstevel@tonic-gate  * An additional ctf_list_t is used to store the head (l_next) and tail
377c478bd9Sstevel@tonic-gate  * (l_prev) pointers.  The current head and tail list elements have their
387c478bd9Sstevel@tonic-gate  * previous and next pointers set to NULL, respectively.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate void
ctf_list_append(ctf_list_t * lp,void * new)417c478bd9Sstevel@tonic-gate ctf_list_append(ctf_list_t *lp, void *new)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	ctf_list_t *p = lp->l_prev;	/* p = tail list element */
447c478bd9Sstevel@tonic-gate 	ctf_list_t *q = new;		/* q = new list element */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	lp->l_prev = q;
477c478bd9Sstevel@tonic-gate 	q->l_prev = p;
487c478bd9Sstevel@tonic-gate 	q->l_next = NULL;
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 	if (p != NULL)
517c478bd9Sstevel@tonic-gate 		p->l_next = q;
527c478bd9Sstevel@tonic-gate 	else
537c478bd9Sstevel@tonic-gate 		lp->l_next = q;
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  * Prepend the specified existing element to the given ctf_list_t.  The
587c478bd9Sstevel@tonic-gate  * existing pointer should be pointing at a struct with embedded ctf_list_t.
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate void
ctf_list_prepend(ctf_list_t * lp,void * new)617c478bd9Sstevel@tonic-gate ctf_list_prepend(ctf_list_t *lp, void *new)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	ctf_list_t *p = new;		/* p = new list element */
647c478bd9Sstevel@tonic-gate 	ctf_list_t *q = lp->l_next;	/* q = head list element */
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	lp->l_next = p;
677c478bd9Sstevel@tonic-gate 	p->l_prev = NULL;
687c478bd9Sstevel@tonic-gate 	p->l_next = q;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	if (q != NULL)
717c478bd9Sstevel@tonic-gate 		q->l_prev = p;
727c478bd9Sstevel@tonic-gate 	else
737c478bd9Sstevel@tonic-gate 		lp->l_prev = p;
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate 
76bc1f688bSRobert Mustacchi void
ctf_list_insert_before(ctf_list_t * head,void * item,void * nitem)77bc1f688bSRobert Mustacchi ctf_list_insert_before(ctf_list_t *head, void *item, void *nitem)
78bc1f688bSRobert Mustacchi {
79bc1f688bSRobert Mustacchi 	ctf_list_t *lp = item;
80bc1f688bSRobert Mustacchi 	ctf_list_t *new = nitem;
81bc1f688bSRobert Mustacchi 	ctf_list_t *prev = lp->l_prev;
82bc1f688bSRobert Mustacchi 
83bc1f688bSRobert Mustacchi 	lp->l_prev = new;
84bc1f688bSRobert Mustacchi 	new->l_next = lp;
85bc1f688bSRobert Mustacchi 	new->l_prev = prev;
86bc1f688bSRobert Mustacchi 	if (prev != NULL) {
87bc1f688bSRobert Mustacchi 		prev->l_next = new;
88bc1f688bSRobert Mustacchi 	} else {
89bc1f688bSRobert Mustacchi 		ASSERT(head->l_next == lp);
90bc1f688bSRobert Mustacchi 		head->l_next = new;
91bc1f688bSRobert Mustacchi 	}
92bc1f688bSRobert Mustacchi }
93bc1f688bSRobert Mustacchi 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Delete the specified existing element from the given ctf_list_t.  The
967c478bd9Sstevel@tonic-gate  * existing pointer should be pointing at a struct with embedded ctf_list_t.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate void
ctf_list_delete(ctf_list_t * lp,void * existing)997c478bd9Sstevel@tonic-gate ctf_list_delete(ctf_list_t *lp, void *existing)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	ctf_list_t *p = existing;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	if (p->l_prev != NULL)
1047c478bd9Sstevel@tonic-gate 		p->l_prev->l_next = p->l_next;
1057c478bd9Sstevel@tonic-gate 	else
1067c478bd9Sstevel@tonic-gate 		lp->l_next = p->l_next;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (p->l_next != NULL)
1097c478bd9Sstevel@tonic-gate 		p->l_next->l_prev = p->l_prev;
1107c478bd9Sstevel@tonic-gate 	else
1117c478bd9Sstevel@tonic-gate 		lp->l_prev = p->l_prev;
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * Convert an encoded CTF string name into a pointer to a C string by looking
1167c478bd9Sstevel@tonic-gate  * up the appropriate string table buffer and then adding the offset.
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate const char *
ctf_strraw(ctf_file_t * fp,uint_t name)1197c478bd9Sstevel@tonic-gate ctf_strraw(ctf_file_t *fp, uint_t name)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET(name) < ctsp->cts_len)
1247c478bd9Sstevel@tonic-gate 		return (ctsp->cts_strs + CTF_NAME_OFFSET(name));
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	/* string table not loaded or corrupt offset */
1277c478bd9Sstevel@tonic-gate 	return (NULL);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate const char *
ctf_strptr(ctf_file_t * fp,uint_t name)1317c478bd9Sstevel@tonic-gate ctf_strptr(ctf_file_t *fp, uint_t name)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	const char *s = ctf_strraw(fp, name);
1347c478bd9Sstevel@tonic-gate 	return (s != NULL ? s : "(?)");
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * Same strdup(3C), but use ctf_alloc() to do the memory allocation.
1397c478bd9Sstevel@tonic-gate  */
1407c478bd9Sstevel@tonic-gate char *
ctf_strdup(const char * s1)1417c478bd9Sstevel@tonic-gate ctf_strdup(const char *s1)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	char *s2 = ctf_alloc(strlen(s1) + 1);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (s2 != NULL)
1467c478bd9Sstevel@tonic-gate 		(void) strcpy(s2, s1);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	return (s2);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
151*88a08813SAndy Fiddaman /*
152*88a08813SAndy Fiddaman  * Free a string which was allocated via ctf_alloc()
153*88a08813SAndy Fiddaman  */
154*88a08813SAndy Fiddaman void
ctf_strfree(char * s)155*88a08813SAndy Fiddaman ctf_strfree(char *s)
156*88a08813SAndy Fiddaman {
157*88a08813SAndy Fiddaman 	if (s == NULL)
158*88a08813SAndy Fiddaman 		return;
159*88a08813SAndy Fiddaman 	ctf_free(s, strlen(s) + 1);
160*88a08813SAndy Fiddaman }
161*88a08813SAndy Fiddaman 
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate  * Store the specified error code into errp if it is non-NULL, and then
1647c478bd9Sstevel@tonic-gate  * return NULL for the benefit of the caller.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate ctf_file_t *
ctf_set_open_errno(int * errp,int error)1677c478bd9Sstevel@tonic-gate ctf_set_open_errno(int *errp, int error)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate 	if (errp != NULL)
1707c478bd9Sstevel@tonic-gate 		*errp = error;
1717c478bd9Sstevel@tonic-gate 	return (NULL);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  * Store the specified error code into the CTF container, and then return
1767c478bd9Sstevel@tonic-gate  * CTF_ERR for the benefit of the caller.
1777c478bd9Sstevel@tonic-gate  */
1787c478bd9Sstevel@tonic-gate long
ctf_set_errno(ctf_file_t * fp,int err)1797c478bd9Sstevel@tonic-gate ctf_set_errno(ctf_file_t *fp, int err)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate 	fp->ctf_errno = err;
1827c478bd9Sstevel@tonic-gate 	return (CTF_ERR);
1837c478bd9Sstevel@tonic-gate }
184bc1f688bSRobert Mustacchi 
185bc1f688bSRobert Mustacchi boolean_t
ctf_sym_valid(uintptr_t strbase,int type,uint16_t shndx,uint64_t val,uint32_t noff)186bc1f688bSRobert Mustacchi ctf_sym_valid(uintptr_t strbase, int type, uint16_t shndx, uint64_t val,
187bc1f688bSRobert Mustacchi     uint32_t noff)
188bc1f688bSRobert Mustacchi {
189bc1f688bSRobert Mustacchi 	const char *name;
190bc1f688bSRobert Mustacchi 
191bc1f688bSRobert Mustacchi 	if (type != STT_OBJECT && type != STT_FUNC)
192bc1f688bSRobert Mustacchi 		return (B_FALSE);
193bc1f688bSRobert Mustacchi 	if (shndx == SHN_UNDEF || noff == 0)
194bc1f688bSRobert Mustacchi 		return (B_FALSE);
195bc1f688bSRobert Mustacchi 	if (type == STT_OBJECT && shndx == SHN_ABS && val == 0)
196bc1f688bSRobert Mustacchi 		return (B_FALSE);
197bc1f688bSRobert Mustacchi 	name = (char *)(strbase + noff);
198bc1f688bSRobert Mustacchi 	if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0)
199bc1f688bSRobert Mustacchi 		return (B_FALSE);
200bc1f688bSRobert Mustacchi 
201bc1f688bSRobert Mustacchi 	return (B_TRUE);
202bc1f688bSRobert Mustacchi }
203