18e458de0SRobert Mustacchi /*
28e458de0SRobert Mustacchi  * This file and its contents are supplied under the terms of the
38e458de0SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
48e458de0SRobert Mustacchi  * You may only use this file in accordance with the terms of version
58e458de0SRobert Mustacchi  * 1.0 of the CDDL.
68e458de0SRobert Mustacchi  *
78e458de0SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
88e458de0SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
98e458de0SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
108e458de0SRobert Mustacchi  */
118e458de0SRobert Mustacchi 
128e458de0SRobert Mustacchi /*
138e458de0SRobert Mustacchi  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
148e458de0SRobert Mustacchi  * Use is subject to license terms.
158e458de0SRobert Mustacchi  */
168e458de0SRobert Mustacchi 
178e458de0SRobert Mustacchi /*
188e458de0SRobert Mustacchi  * Copyright 2021 Oxide Computer Company
198e458de0SRobert Mustacchi  */
208e458de0SRobert Mustacchi 
218e458de0SRobert Mustacchi #ifndef	_KERNEL
228e458de0SRobert Mustacchi #include <stdlib.h>
238e458de0SRobert Mustacchi #include <strings.h>
248e458de0SRobert Mustacchi #include <stddef.h>
258e458de0SRobert Mustacchi #else
268e458de0SRobert Mustacchi #include <sys/types.h>
278e458de0SRobert Mustacchi #include <sys/kmem.h>
288e458de0SRobert Mustacchi #include <sys/ddi.h>
298e458de0SRobert Mustacchi #include <sys/sunddi.h>
308e458de0SRobert Mustacchi #include <sys/stddef.h>
318e458de0SRobert Mustacchi #endif	/* _KERNEL */
328e458de0SRobert Mustacchi 
338e458de0SRobert Mustacchi #include <core_shstrtab.h>
348e458de0SRobert Mustacchi 
358e458de0SRobert Mustacchi const char *shstrtab_data[STR_NUM] = {
368e458de0SRobert Mustacchi 	"",
378e458de0SRobert Mustacchi 	".SUNW_ctf",
388e458de0SRobert Mustacchi 	".symtab",
398e458de0SRobert Mustacchi 	".dynsym",
408e458de0SRobert Mustacchi 	".strtab",
418e458de0SRobert Mustacchi 	".dynstr",
428e458de0SRobert Mustacchi 	".shstrtab"
438e458de0SRobert Mustacchi };
448e458de0SRobert Mustacchi 
458e458de0SRobert Mustacchi static void *
shstrtab_alloc(void)468e458de0SRobert Mustacchi shstrtab_alloc(void)
478e458de0SRobert Mustacchi {
488e458de0SRobert Mustacchi #ifdef	_KERNEL
49*ca783257SDan McDonald 	return (kmem_zalloc(sizeof (shstrtab_ent_t), KM_NOSLEEP_LAZY));
508e458de0SRobert Mustacchi #else
518e458de0SRobert Mustacchi 	return (calloc(1, sizeof (shstrtab_ent_t)));
528e458de0SRobert Mustacchi #endif
538e458de0SRobert Mustacchi }
548e458de0SRobert Mustacchi 
558e458de0SRobert Mustacchi static void
shstrtab_free(shstrtab_ent_t * ent)568e458de0SRobert Mustacchi shstrtab_free(shstrtab_ent_t *ent)
578e458de0SRobert Mustacchi {
588e458de0SRobert Mustacchi #ifdef	_KERNEL
598e458de0SRobert Mustacchi 	if (ent->sste_name != NULL) {
608e458de0SRobert Mustacchi 		strfree(ent->sste_name);
618e458de0SRobert Mustacchi 	}
628e458de0SRobert Mustacchi 	kmem_free(ent, sizeof (*ent));
638e458de0SRobert Mustacchi #else
648e458de0SRobert Mustacchi 	free(ent->sste_name);
658e458de0SRobert Mustacchi 	free(ent);
668e458de0SRobert Mustacchi #endif
678e458de0SRobert Mustacchi }
688e458de0SRobert Mustacchi 
698e458de0SRobert Mustacchi 
708e458de0SRobert Mustacchi boolean_t
shstrtab_ndx(shstrtab_t * s,const char * name,Elf32_Word * offp)718e458de0SRobert Mustacchi shstrtab_ndx(shstrtab_t *s, const char *name, Elf32_Word *offp)
728e458de0SRobert Mustacchi {
738e458de0SRobert Mustacchi 	shstrtab_ent_t *ent;
748e458de0SRobert Mustacchi 
758e458de0SRobert Mustacchi 	for (ent = list_head(&s->sst_names); ent != NULL;
768e458de0SRobert Mustacchi 	    ent = list_next(&s->sst_names, ent)) {
778e458de0SRobert Mustacchi 		if (strcmp(name, ent->sste_name) == 0) {
788e458de0SRobert Mustacchi 			if (offp != NULL)
798e458de0SRobert Mustacchi 				*offp = ent->sste_offset;
808e458de0SRobert Mustacchi 			return (B_TRUE);
818e458de0SRobert Mustacchi 		}
828e458de0SRobert Mustacchi 	}
838e458de0SRobert Mustacchi 
848e458de0SRobert Mustacchi 	ent = shstrtab_alloc();
858e458de0SRobert Mustacchi 	if (ent == NULL) {
868e458de0SRobert Mustacchi 		return (B_FALSE);
878e458de0SRobert Mustacchi 	}
888e458de0SRobert Mustacchi 
898e458de0SRobert Mustacchi 	ent->sste_name = strdup(name);
908e458de0SRobert Mustacchi 	if (ent->sste_name == NULL) {
918e458de0SRobert Mustacchi 		shstrtab_free(ent);
928e458de0SRobert Mustacchi 		return (B_FALSE);
938e458de0SRobert Mustacchi 	}
948e458de0SRobert Mustacchi 	ent->sste_len = strlen(name) + 1;
958e458de0SRobert Mustacchi 	ent->sste_offset = s->sst_len;
968e458de0SRobert Mustacchi 	s->sst_len += ent->sste_len;
978e458de0SRobert Mustacchi 
988e458de0SRobert Mustacchi 	list_insert_tail(&s->sst_names, ent);
998e458de0SRobert Mustacchi 
1008e458de0SRobert Mustacchi 	if (offp != NULL)
1018e458de0SRobert Mustacchi 		*offp = ent->sste_offset;
1028e458de0SRobert Mustacchi 	return (B_TRUE);
1038e458de0SRobert Mustacchi }
1048e458de0SRobert Mustacchi 
1058e458de0SRobert Mustacchi boolean_t
shstrtab_init(shstrtab_t * s)1068e458de0SRobert Mustacchi shstrtab_init(shstrtab_t *s)
1078e458de0SRobert Mustacchi {
1088e458de0SRobert Mustacchi 	bzero(s, sizeof (*s));
1098e458de0SRobert Mustacchi 	list_create(&s->sst_names, sizeof (shstrtab_ent_t),
1108e458de0SRobert Mustacchi 	    offsetof(shstrtab_ent_t, sste_link));
1118e458de0SRobert Mustacchi 
1128e458de0SRobert Mustacchi 	return (shstrtab_ndx(s, shstrtab_data[STR_NONE], NULL));
1138e458de0SRobert Mustacchi }
1148e458de0SRobert Mustacchi 
1158e458de0SRobert Mustacchi void
shstrtab_fini(shstrtab_t * s)1168e458de0SRobert Mustacchi shstrtab_fini(shstrtab_t *s)
1178e458de0SRobert Mustacchi {
1188e458de0SRobert Mustacchi 	shstrtab_ent_t *ent;
1198e458de0SRobert Mustacchi 
1208e458de0SRobert Mustacchi 	if (s->sst_len == 0)
1218e458de0SRobert Mustacchi 		return;
1228e458de0SRobert Mustacchi 
1238e458de0SRobert Mustacchi 	while ((ent = list_remove_head(&s->sst_names)) != NULL) {
1248e458de0SRobert Mustacchi 		shstrtab_free(ent);
1258e458de0SRobert Mustacchi 	}
1268e458de0SRobert Mustacchi }
1278e458de0SRobert Mustacchi 
1288e458de0SRobert Mustacchi size_t
shstrtab_size(const shstrtab_t * s)1298e458de0SRobert Mustacchi shstrtab_size(const shstrtab_t *s)
1308e458de0SRobert Mustacchi {
1318e458de0SRobert Mustacchi 	return (s->sst_len);
1328e458de0SRobert Mustacchi }
1338e458de0SRobert Mustacchi 
1348e458de0SRobert Mustacchi void
shstrtab_dump(shstrtab_t * s,void * buf)1358e458de0SRobert Mustacchi shstrtab_dump(shstrtab_t *s, void *buf)
1368e458de0SRobert Mustacchi {
1378e458de0SRobert Mustacchi 	size_t off = 0;
1388e458de0SRobert Mustacchi 
1398e458de0SRobert Mustacchi 	for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL;
1408e458de0SRobert Mustacchi 	    ent = list_next(&s->sst_names, ent)) {
1418e458de0SRobert Mustacchi 		bcopy(ent->sste_name, buf + off, ent->sste_len);
1428e458de0SRobert Mustacchi 		off += ent->sste_len;
1438e458de0SRobert Mustacchi 	}
1448e458de0SRobert Mustacchi }
145