1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2015, Joyent, Inc. 28 */ 29 30 #include <ctf_impl.h> 31 #include <sys/debug.h> 32 33 /* 34 * Simple doubly-linked list append routine. This implementation assumes that 35 * each list element contains an embedded ctf_list_t as the first member. 36 * An additional ctf_list_t is used to store the head (l_next) and tail 37 * (l_prev) pointers. The current head and tail list elements have their 38 * previous and next pointers set to NULL, respectively. 39 */ 40 void 41 ctf_list_append(ctf_list_t *lp, void *new) 42 { 43 ctf_list_t *p = lp->l_prev; /* p = tail list element */ 44 ctf_list_t *q = new; /* q = new list element */ 45 46 lp->l_prev = q; 47 q->l_prev = p; 48 q->l_next = NULL; 49 50 if (p != NULL) 51 p->l_next = q; 52 else 53 lp->l_next = q; 54 } 55 56 /* 57 * Prepend the specified existing element to the given ctf_list_t. The 58 * existing pointer should be pointing at a struct with embedded ctf_list_t. 59 */ 60 void 61 ctf_list_prepend(ctf_list_t *lp, void *new) 62 { 63 ctf_list_t *p = new; /* p = new list element */ 64 ctf_list_t *q = lp->l_next; /* q = head list element */ 65 66 lp->l_next = p; 67 p->l_prev = NULL; 68 p->l_next = q; 69 70 if (q != NULL) 71 q->l_prev = p; 72 else 73 lp->l_prev = p; 74 } 75 76 void 77 ctf_list_insert_before(ctf_list_t *head, void *item, void *nitem) 78 { 79 ctf_list_t *lp = item; 80 ctf_list_t *new = nitem; 81 ctf_list_t *prev = lp->l_prev; 82 83 lp->l_prev = new; 84 new->l_next = lp; 85 new->l_prev = prev; 86 if (prev != NULL) { 87 prev->l_next = new; 88 } else { 89 ASSERT(head->l_next == lp); 90 head->l_next = new; 91 } 92 } 93 94 /* 95 * Delete the specified existing element from the given ctf_list_t. The 96 * existing pointer should be pointing at a struct with embedded ctf_list_t. 97 */ 98 void 99 ctf_list_delete(ctf_list_t *lp, void *existing) 100 { 101 ctf_list_t *p = existing; 102 103 if (p->l_prev != NULL) 104 p->l_prev->l_next = p->l_next; 105 else 106 lp->l_next = p->l_next; 107 108 if (p->l_next != NULL) 109 p->l_next->l_prev = p->l_prev; 110 else 111 lp->l_prev = p->l_prev; 112 } 113 114 /* 115 * Convert an encoded CTF string name into a pointer to a C string by looking 116 * up the appropriate string table buffer and then adding the offset. 117 */ 118 const char * 119 ctf_strraw(ctf_file_t *fp, uint_t name) 120 { 121 ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)]; 122 123 if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET(name) < ctsp->cts_len) 124 return (ctsp->cts_strs + CTF_NAME_OFFSET(name)); 125 126 /* string table not loaded or corrupt offset */ 127 return (NULL); 128 } 129 130 const char * 131 ctf_strptr(ctf_file_t *fp, uint_t name) 132 { 133 const char *s = ctf_strraw(fp, name); 134 return (s != NULL ? s : "(?)"); 135 } 136 137 /* 138 * Same strdup(3C), but use ctf_alloc() to do the memory allocation. 139 */ 140 char * 141 ctf_strdup(const char *s1) 142 { 143 char *s2 = ctf_alloc(strlen(s1) + 1); 144 145 if (s2 != NULL) 146 (void) strcpy(s2, s1); 147 148 return (s2); 149 } 150 151 /* 152 * Free a string which was allocated via ctf_alloc() 153 */ 154 void 155 ctf_strfree(char *s) 156 { 157 if (s == NULL) 158 return; 159 ctf_free(s, strlen(s) + 1); 160 } 161 162 /* 163 * Store the specified error code into errp if it is non-NULL, and then 164 * return NULL for the benefit of the caller. 165 */ 166 ctf_file_t * 167 ctf_set_open_errno(int *errp, int error) 168 { 169 if (errp != NULL) 170 *errp = error; 171 return (NULL); 172 } 173 174 /* 175 * Store the specified error code into the CTF container, and then return 176 * CTF_ERR for the benefit of the caller. 177 */ 178 long 179 ctf_set_errno(ctf_file_t *fp, int err) 180 { 181 fp->ctf_errno = err; 182 return (CTF_ERR); 183 } 184 185 boolean_t 186 ctf_sym_valid(uintptr_t strbase, int type, uint16_t shndx, uint64_t val, 187 uint32_t noff) 188 { 189 const char *name; 190 191 if (type != STT_OBJECT && type != STT_FUNC) 192 return (B_FALSE); 193 if (shndx == SHN_UNDEF || noff == 0) 194 return (B_FALSE); 195 if (type == STT_OBJECT && shndx == SHN_ABS && val == 0) 196 return (B_FALSE); 197 name = (char *)(strbase + noff); 198 if (strcmp(name, "_START_") == 0 || strcmp(name, "_END_") == 0) 199 return (B_FALSE); 200 201 return (B_TRUE); 202 } 203