1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 14 * Use is subject to license terms. 15 */ 16 17 /* 18 * Copyright 2021 Oxide Computer Company 19 */ 20 21 #ifndef _KERNEL 22 #include <stdlib.h> 23 #include <strings.h> 24 #include <stddef.h> 25 #else 26 #include <sys/types.h> 27 #include <sys/kmem.h> 28 #include <sys/ddi.h> 29 #include <sys/sunddi.h> 30 #include <sys/stddef.h> 31 #endif /* _KERNEL */ 32 33 #include <core_shstrtab.h> 34 35 const char *shstrtab_data[STR_NUM] = { 36 "", 37 ".SUNW_ctf", 38 ".symtab", 39 ".dynsym", 40 ".strtab", 41 ".dynstr", 42 ".shstrtab" 43 }; 44 45 static void * 46 shstrtab_alloc(void) 47 { 48 #ifdef _KERNEL 49 return (kmem_zalloc(sizeof (shstrtab_ent_t), 50 KM_NOSLEEP | KM_NORMALPRI)); 51 #else 52 return (calloc(1, sizeof (shstrtab_ent_t))); 53 #endif 54 } 55 56 static void 57 shstrtab_free(shstrtab_ent_t *ent) 58 { 59 #ifdef _KERNEL 60 if (ent->sste_name != NULL) { 61 strfree(ent->sste_name); 62 } 63 kmem_free(ent, sizeof (*ent)); 64 #else 65 free(ent->sste_name); 66 free(ent); 67 #endif 68 } 69 70 71 boolean_t 72 shstrtab_ndx(shstrtab_t *s, const char *name, Elf32_Word *offp) 73 { 74 shstrtab_ent_t *ent; 75 76 for (ent = list_head(&s->sst_names); ent != NULL; 77 ent = list_next(&s->sst_names, ent)) { 78 if (strcmp(name, ent->sste_name) == 0) { 79 if (offp != NULL) 80 *offp = ent->sste_offset; 81 return (B_TRUE); 82 } 83 } 84 85 ent = shstrtab_alloc(); 86 if (ent == NULL) { 87 return (B_FALSE); 88 } 89 90 ent->sste_name = strdup(name); 91 if (ent->sste_name == NULL) { 92 shstrtab_free(ent); 93 return (B_FALSE); 94 } 95 ent->sste_len = strlen(name) + 1; 96 ent->sste_offset = s->sst_len; 97 s->sst_len += ent->sste_len; 98 99 list_insert_tail(&s->sst_names, ent); 100 101 if (offp != NULL) 102 *offp = ent->sste_offset; 103 return (B_TRUE); 104 } 105 106 boolean_t 107 shstrtab_init(shstrtab_t *s) 108 { 109 bzero(s, sizeof (*s)); 110 list_create(&s->sst_names, sizeof (shstrtab_ent_t), 111 offsetof(shstrtab_ent_t, sste_link)); 112 113 return (shstrtab_ndx(s, shstrtab_data[STR_NONE], NULL)); 114 } 115 116 void 117 shstrtab_fini(shstrtab_t *s) 118 { 119 shstrtab_ent_t *ent; 120 121 if (s->sst_len == 0) 122 return; 123 124 while ((ent = list_remove_head(&s->sst_names)) != NULL) { 125 shstrtab_free(ent); 126 } 127 } 128 129 size_t 130 shstrtab_size(const shstrtab_t *s) 131 { 132 return (s->sst_len); 133 } 134 135 void 136 shstrtab_dump(shstrtab_t *s, void *buf) 137 { 138 size_t off = 0; 139 140 for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL; 141 ent = list_next(&s->sst_names, ent)) { 142 bcopy(ent->sste_name, buf + off, ent->sste_len); 143 off += ent->sste_len; 144 } 145 } 146