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