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*7fd79137SRobert Mustacchi /* 27*7fd79137SRobert Mustacchi * Copyright (c) 2015, Joyent, Inc. 28*7fd79137SRobert Mustacchi */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <ctf_impl.h> 31*7fd79137SRobert 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 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 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*7fd79137SRobert Mustacchi void 77*7fd79137SRobert Mustacchi ctf_list_insert_before(ctf_list_t *head, void *item, void *nitem) 78*7fd79137SRobert Mustacchi { 79*7fd79137SRobert Mustacchi ctf_list_t *lp = item; 80*7fd79137SRobert Mustacchi ctf_list_t *new = nitem; 81*7fd79137SRobert Mustacchi ctf_list_t *prev = lp->l_prev; 82*7fd79137SRobert Mustacchi 83*7fd79137SRobert Mustacchi lp->l_prev = new; 84*7fd79137SRobert Mustacchi new->l_next = lp; 85*7fd79137SRobert Mustacchi new->l_prev = prev; 86*7fd79137SRobert Mustacchi if (prev != NULL) { 87*7fd79137SRobert Mustacchi prev->l_next = new; 88*7fd79137SRobert Mustacchi } else { 89*7fd79137SRobert Mustacchi ASSERT(head->l_next == lp); 90*7fd79137SRobert Mustacchi head->l_next = new; 91*7fd79137SRobert Mustacchi } 92*7fd79137SRobert Mustacchi } 93*7fd79137SRobert 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 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 * 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 * 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 * 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 * 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 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*7fd79137SRobert Mustacchi 174*7fd79137SRobert Mustacchi boolean_t 175*7fd79137SRobert Mustacchi ctf_sym_valid(uintptr_t strbase, int type, uint16_t shndx, uint64_t val, 176*7fd79137SRobert Mustacchi uint32_t noff) 177*7fd79137SRobert Mustacchi { 178*7fd79137SRobert Mustacchi const char *name; 179*7fd79137SRobert Mustacchi 180*7fd79137SRobert Mustacchi if (type != STT_OBJECT && type != STT_FUNC) 181*7fd79137SRobert Mustacchi return (B_FALSE); 182*7fd79137SRobert Mustacchi if (shndx == SHN_UNDEF || noff == 0) 183*7fd79137SRobert Mustacchi return (B_FALSE); 184*7fd79137SRobert Mustacchi if (type == STT_OBJECT && shndx == SHN_ABS && val == 0) 185*7fd79137SRobert Mustacchi return (B_FALSE); 186*7fd79137SRobert Mustacchi name = (char *)(strbase + noff); 187*7fd79137SRobert Mustacchi if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0) 188*7fd79137SRobert Mustacchi return (B_FALSE); 189*7fd79137SRobert Mustacchi 190*7fd79137SRobert Mustacchi return (B_TRUE); 191*7fd79137SRobert Mustacchi } 192