xref: /titanic_50/usr/src/common/ctf/ctf_util.c (revision f3e7f55e73a39377d55a030f124cc86b3b66a9cc)
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  */
26*f3e7f55eSRobert Mustacchi /*
27*f3e7f55eSRobert Mustacchi  * Copyright (c) 2015, Joyent, Inc.
28*f3e7f55eSRobert Mustacchi  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <ctf_impl.h>
31*f3e7f55eSRobert 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 
76*f3e7f55eSRobert Mustacchi void
ctf_list_insert_before(ctf_list_t * head,void * item,void * nitem)77*f3e7f55eSRobert Mustacchi ctf_list_insert_before(ctf_list_t *head, void *item, void *nitem)
78*f3e7f55eSRobert Mustacchi {
79*f3e7f55eSRobert Mustacchi 	ctf_list_t *lp = item;
80*f3e7f55eSRobert Mustacchi 	ctf_list_t *new = nitem;
81*f3e7f55eSRobert Mustacchi 	ctf_list_t *prev = lp->l_prev;
82*f3e7f55eSRobert Mustacchi 
83*f3e7f55eSRobert Mustacchi 	lp->l_prev = new;
84*f3e7f55eSRobert Mustacchi 	new->l_next = lp;
85*f3e7f55eSRobert Mustacchi 	new->l_prev = prev;
86*f3e7f55eSRobert Mustacchi 	if (prev != NULL) {
87*f3e7f55eSRobert Mustacchi 		prev->l_next = new;
88*f3e7f55eSRobert Mustacchi 	} else {
89*f3e7f55eSRobert Mustacchi 		ASSERT(head->l_next == lp);
90*f3e7f55eSRobert Mustacchi 		head->l_next = new;
91*f3e7f55eSRobert Mustacchi 	}
92*f3e7f55eSRobert Mustacchi }
93*f3e7f55eSRobert 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 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * Store the specified error code into errp if it is non-NULL, and then
1537c478bd9Sstevel@tonic-gate  * return NULL for the benefit of the caller.
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate ctf_file_t *
ctf_set_open_errno(int * errp,int error)1567c478bd9Sstevel@tonic-gate ctf_set_open_errno(int *errp, int error)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	if (errp != NULL)
1597c478bd9Sstevel@tonic-gate 		*errp = error;
1607c478bd9Sstevel@tonic-gate 	return (NULL);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * Store the specified error code into the CTF container, and then return
1657c478bd9Sstevel@tonic-gate  * CTF_ERR for the benefit of the caller.
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate long
ctf_set_errno(ctf_file_t * fp,int err)1687c478bd9Sstevel@tonic-gate ctf_set_errno(ctf_file_t *fp, int err)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	fp->ctf_errno = err;
1717c478bd9Sstevel@tonic-gate 	return (CTF_ERR);
1727c478bd9Sstevel@tonic-gate }
173*f3e7f55eSRobert Mustacchi 
174*f3e7f55eSRobert Mustacchi boolean_t
ctf_sym_valid(uintptr_t strbase,int type,uint16_t shndx,uint64_t val,uint32_t noff)175*f3e7f55eSRobert Mustacchi ctf_sym_valid(uintptr_t strbase, int type, uint16_t shndx, uint64_t val,
176*f3e7f55eSRobert Mustacchi     uint32_t noff)
177*f3e7f55eSRobert Mustacchi {
178*f3e7f55eSRobert Mustacchi 	const char *name;
179*f3e7f55eSRobert Mustacchi 
180*f3e7f55eSRobert Mustacchi 	if (type != STT_OBJECT && type != STT_FUNC)
181*f3e7f55eSRobert Mustacchi 		return (B_FALSE);
182*f3e7f55eSRobert Mustacchi 	if (shndx == SHN_UNDEF || noff == 0)
183*f3e7f55eSRobert Mustacchi 		return (B_FALSE);
184*f3e7f55eSRobert Mustacchi 	if (type == STT_OBJECT && shndx == SHN_ABS && val == 0)
185*f3e7f55eSRobert Mustacchi 		return (B_FALSE);
186*f3e7f55eSRobert Mustacchi 	name = (char *)(strbase + noff);
187*f3e7f55eSRobert Mustacchi 	if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0)
188*f3e7f55eSRobert Mustacchi 		return (B_FALSE);
189*f3e7f55eSRobert Mustacchi 
190*f3e7f55eSRobert Mustacchi 	return (B_TRUE);
191*f3e7f55eSRobert Mustacchi }
192