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), KM_NOSLEEP_LAZY)); 50 #else 51 return (calloc(1, sizeof (shstrtab_ent_t))); 52 #endif 53 } 54 55 static void 56 shstrtab_free(shstrtab_ent_t *ent) 57 { 58 #ifdef _KERNEL 59 if (ent->sste_name != NULL) { 60 strfree(ent->sste_name); 61 } 62 kmem_free(ent, sizeof (*ent)); 63 #else 64 free(ent->sste_name); 65 free(ent); 66 #endif 67 } 68 69 70 boolean_t 71 shstrtab_ndx(shstrtab_t *s, const char *name, Elf32_Word *offp) 72 { 73 shstrtab_ent_t *ent; 74 75 for (ent = list_head(&s->sst_names); ent != NULL; 76 ent = list_next(&s->sst_names, ent)) { 77 if (strcmp(name, ent->sste_name) == 0) { 78 if (offp != NULL) 79 *offp = ent->sste_offset; 80 return (B_TRUE); 81 } 82 } 83 84 ent = shstrtab_alloc(); 85 if (ent == NULL) { 86 return (B_FALSE); 87 } 88 89 ent->sste_name = strdup(name); 90 if (ent->sste_name == NULL) { 91 shstrtab_free(ent); 92 return (B_FALSE); 93 } 94 ent->sste_len = strlen(name) + 1; 95 ent->sste_offset = s->sst_len; 96 s->sst_len += ent->sste_len; 97 98 list_insert_tail(&s->sst_names, ent); 99 100 if (offp != NULL) 101 *offp = ent->sste_offset; 102 return (B_TRUE); 103 } 104 105 boolean_t 106 shstrtab_init(shstrtab_t *s) 107 { 108 bzero(s, sizeof (*s)); 109 list_create(&s->sst_names, sizeof (shstrtab_ent_t), 110 offsetof(shstrtab_ent_t, sste_link)); 111 112 return (shstrtab_ndx(s, shstrtab_data[STR_NONE], NULL)); 113 } 114 115 void 116 shstrtab_fini(shstrtab_t *s) 117 { 118 shstrtab_ent_t *ent; 119 120 if (s->sst_len == 0) 121 return; 122 123 while ((ent = list_remove_head(&s->sst_names)) != NULL) { 124 shstrtab_free(ent); 125 } 126 } 127 128 size_t 129 shstrtab_size(const shstrtab_t *s) 130 { 131 return (s->sst_len); 132 } 133 134 void 135 shstrtab_dump(shstrtab_t *s, void *buf) 136 { 137 size_t off = 0; 138 139 for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL; 140 ent = list_next(&s->sst_names, ent)) { 141 bcopy(ent->sste_name, buf + off, ent->sste_len); 142 off += ent->sste_len; 143 } 144 } 145