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