1 /* Miscellaneous utilities. 2 Copyright (C) 2019-2020 Free Software Foundation, Inc. 3 4 This file is part of libctf. 5 6 libctf is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 This program is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 See the GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; see the file COPYING. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include <ctf-impl.h> 21 #include <string.h> 22 23 /* Simple doubly-linked list append routine. This implementation assumes that 24 each list element contains an embedded ctf_list_t as the first member. 25 An additional ctf_list_t is used to store the head (l_next) and tail 26 (l_prev) pointers. The current head and tail list elements have their 27 previous and next pointers set to NULL, respectively. */ 28 29 void 30 ctf_list_append (ctf_list_t *lp, void *newp) 31 { 32 ctf_list_t *p = lp->l_prev; /* p = tail list element. */ 33 ctf_list_t *q = newp; /* q = new list element. */ 34 35 lp->l_prev = q; 36 q->l_prev = p; 37 q->l_next = NULL; 38 39 if (p != NULL) 40 p->l_next = q; 41 else 42 lp->l_next = q; 43 } 44 45 /* Prepend the specified existing element to the given ctf_list_t. The 46 existing pointer should be pointing at a struct with embedded ctf_list_t. */ 47 48 void 49 ctf_list_prepend (ctf_list_t * lp, void *newp) 50 { 51 ctf_list_t *p = newp; /* p = new list element. */ 52 ctf_list_t *q = lp->l_next; /* q = head list element. */ 53 54 lp->l_next = p; 55 p->l_prev = NULL; 56 p->l_next = q; 57 58 if (q != NULL) 59 q->l_prev = p; 60 else 61 lp->l_prev = p; 62 } 63 64 /* Delete the specified existing element from the given ctf_list_t. The 65 existing pointer should be pointing at a struct with embedded ctf_list_t. */ 66 67 void 68 ctf_list_delete (ctf_list_t *lp, void *existing) 69 { 70 ctf_list_t *p = existing; 71 72 if (p->l_prev != NULL) 73 p->l_prev->l_next = p->l_next; 74 else 75 lp->l_next = p->l_next; 76 77 if (p->l_next != NULL) 78 p->l_next->l_prev = p->l_prev; 79 else 80 lp->l_prev = p->l_prev; 81 } 82 83 /* Return 1 if the list is empty. */ 84 85 int 86 ctf_list_empty_p (ctf_list_t *lp) 87 { 88 return (lp->l_next == NULL && lp->l_prev == NULL); 89 } 90 91 /* Splice one entire list onto the end of another one. The existing list is 92 emptied. */ 93 94 void 95 ctf_list_splice (ctf_list_t *lp, ctf_list_t *append) 96 { 97 if (ctf_list_empty_p (append)) 98 return; 99 100 if (lp->l_prev != NULL) 101 lp->l_prev->l_next = append->l_next; 102 else 103 lp->l_next = append->l_next; 104 105 append->l_next->l_prev = lp->l_prev; 106 lp->l_prev = append->l_prev; 107 append->l_next = NULL; 108 append->l_prev = NULL; 109 } 110 111 /* Convert a 32-bit ELF symbol into Elf64 and return a pointer to it. */ 112 113 Elf64_Sym * 114 ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst) 115 { 116 dst->st_name = src->st_name; 117 dst->st_value = src->st_value; 118 dst->st_size = src->st_size; 119 dst->st_info = src->st_info; 120 dst->st_other = src->st_other; 121 dst->st_shndx = src->st_shndx; 122 123 return dst; 124 } 125 126 /* A string appender working on dynamic strings. Returns NULL on OOM. */ 127 128 char * 129 ctf_str_append (char *s, const char *append) 130 { 131 size_t s_len = 0; 132 133 if (append == NULL) 134 return s; 135 136 if (s != NULL) 137 s_len = strlen (s); 138 139 size_t append_len = strlen (append); 140 141 if ((s = realloc (s, s_len + append_len + 1)) == NULL) 142 return NULL; 143 144 memcpy (s + s_len, append, append_len); 145 s[s_len + append_len] = '\0'; 146 147 return s; 148 } 149 150 /* A version of ctf_str_append that returns the old string on OOM. */ 151 152 char * 153 ctf_str_append_noerr (char *s, const char *append) 154 { 155 char *new_s; 156 157 new_s = ctf_str_append (s, append); 158 if (!new_s) 159 return s; 160 return new_s; 161 } 162 163 /* A realloc() that fails noisily if called with any ctf_str_num_users. */ 164 void * 165 ctf_realloc (ctf_file_t *fp, void *ptr, size_t size) 166 { 167 if (fp->ctf_str_num_refs > 0) 168 { 169 ctf_dprintf ("%p: attempt to realloc() string table with %lu active refs\n", 170 (void *) fp, (unsigned long) fp->ctf_str_num_refs); 171 return NULL; 172 } 173 return realloc (ptr, size); 174 } 175 176 /* Store the specified error code into errp if it is non-NULL, and then 177 return NULL for the benefit of the caller. */ 178 179 void * 180 ctf_set_open_errno (int *errp, int error) 181 { 182 if (errp != NULL) 183 *errp = error; 184 return NULL; 185 } 186 187 /* Store the specified error code into the CTF container, and then return 188 CTF_ERR / -1 for the benefit of the caller. */ 189 190 unsigned long 191 ctf_set_errno (ctf_file_t * fp, int err) 192 { 193 fp->ctf_errno = err; 194 return CTF_ERR; 195 } 196 197 /* Create a ctf_next_t. */ 198 199 ctf_next_t * 200 ctf_next_create (void) 201 { 202 return calloc (1, sizeof (struct ctf_next)); 203 } 204 205 /* Destroy a ctf_next_t, for early exit from iterators. */ 206 207 void 208 ctf_next_destroy (ctf_next_t *i) 209 { 210 if (i == NULL) 211 return; 212 213 if (i->ctn_iter_fun == (void (*) (void)) ctf_dynhash_next_sorted) 214 free (i->u.ctn_sorted_hkv); 215 free (i); 216 } 217 218 /* Copy a ctf_next_t. */ 219 220 ctf_next_t * 221 ctf_next_copy (ctf_next_t *i) 222 { 223 ctf_next_t *i2; 224 225 if ((i2 = ctf_next_create()) == NULL) 226 return NULL; 227 memcpy (i2, i, sizeof (struct ctf_next)); 228 229 if (i2->ctn_iter_fun == (void (*) (void)) ctf_dynhash_next_sorted) 230 { 231 size_t els = ctf_dynhash_elements ((ctf_dynhash_t *) i->cu.ctn_h); 232 if ((i2->u.ctn_sorted_hkv = calloc (els, sizeof (ctf_next_hkv_t))) == NULL) 233 { 234 free (i2); 235 return NULL; 236 } 237 memcpy (i2->u.ctn_sorted_hkv, i->u.ctn_sorted_hkv, 238 els * sizeof (ctf_next_hkv_t)); 239 } 240 return i2; 241 } 242