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 }