xref: /freebsd/contrib/elftoolchain/libelftc/elftc_demangle.c (revision 0fe0fe112fa6cc220f14a1a9196b51fdc79edc72)
1a85fe12eSEd Maste /*-
2a85fe12eSEd Maste  * Copyright (c) 2009 Kai Wang
3a85fe12eSEd Maste  * All rights reserved.
4a85fe12eSEd Maste  *
5a85fe12eSEd Maste  * Redistribution and use in source and binary forms, with or without
6a85fe12eSEd Maste  * modification, are permitted provided that the following conditions
7a85fe12eSEd Maste  * are met:
8a85fe12eSEd Maste  * 1. Redistributions of source code must retain the above copyright
9a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer
10a85fe12eSEd Maste  *    in this position and unchanged.
11a85fe12eSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
12a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer in the
13a85fe12eSEd Maste  *    documentation and/or other materials provided with the distribution.
14a85fe12eSEd Maste  *
15a85fe12eSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16a85fe12eSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17a85fe12eSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18a85fe12eSEd Maste  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19a85fe12eSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20a85fe12eSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a85fe12eSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a85fe12eSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a85fe12eSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24a85fe12eSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a85fe12eSEd Maste  */
26a85fe12eSEd Maste 
27a85fe12eSEd Maste #include <sys/param.h>
28a85fe12eSEd Maste #include <assert.h>
29a85fe12eSEd Maste #include <errno.h>
30a85fe12eSEd Maste #include <libelftc.h>
31a85fe12eSEd Maste #include <stdlib.h>
32a85fe12eSEd Maste #include <string.h>
33a85fe12eSEd Maste 
34a85fe12eSEd Maste #include "_libelftc.h"
35a85fe12eSEd Maste 
36*839529caSEd Maste ELFTC_VCSID("$Id: elftc_demangle.c 3296 2016-01-09 14:17:28Z jkoshy $");
37a85fe12eSEd Maste 
38*839529caSEd Maste static unsigned int
is_mangled(const char * s,unsigned int style)39*839529caSEd Maste is_mangled(const char *s, unsigned int style)
40a85fe12eSEd Maste {
41a85fe12eSEd Maste 
42a85fe12eSEd Maste 	switch (style) {
43a85fe12eSEd Maste 	case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0);
44a85fe12eSEd Maste 	case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0);
45a85fe12eSEd Maste 	case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0);
46a85fe12eSEd Maste 	}
47a85fe12eSEd Maste 
48a85fe12eSEd Maste 	/* No style or invalid style spcified, try to guess. */
49a85fe12eSEd Maste 	if (is_cpp_mangled_gnu3(s))
50a85fe12eSEd Maste 		return (ELFTC_DEM_GNU3);
51a85fe12eSEd Maste 	if (is_cpp_mangled_gnu2(s))
52a85fe12eSEd Maste 		return (ELFTC_DEM_GNU2);
53a85fe12eSEd Maste 	if (is_cpp_mangled_ARM(s))
54a85fe12eSEd Maste 		return (ELFTC_DEM_ARM);
55a85fe12eSEd Maste 
56a85fe12eSEd Maste 	/* Cannot be demangled. */
57a85fe12eSEd Maste 	return (0);
58a85fe12eSEd Maste }
59a85fe12eSEd Maste 
60a85fe12eSEd Maste static char *
demangle(const char * s,unsigned int style,unsigned int rc)61*839529caSEd Maste demangle(const char *s, unsigned int style, unsigned int rc)
62a85fe12eSEd Maste {
63a85fe12eSEd Maste 
64a85fe12eSEd Maste 	(void) rc;			/* XXX */
65a85fe12eSEd Maste 	switch (style) {
66a85fe12eSEd Maste 	case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s));
67a85fe12eSEd Maste 	case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s));
68a85fe12eSEd Maste 	case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s));
69a85fe12eSEd Maste 	default:
70a85fe12eSEd Maste 		assert(0);
71a85fe12eSEd Maste 		return (NULL);
72a85fe12eSEd Maste 	}
73a85fe12eSEd Maste }
74a85fe12eSEd Maste 
75a85fe12eSEd Maste int
elftc_demangle(const char * mangledname,char * buffer,size_t bufsize,unsigned int flags)76a85fe12eSEd Maste elftc_demangle(const char *mangledname, char *buffer, size_t bufsize,
77a85fe12eSEd Maste     unsigned int flags)
78a85fe12eSEd Maste {
79*839529caSEd Maste 	unsigned int style, rc;
80a85fe12eSEd Maste 	char *rlt;
81a85fe12eSEd Maste 
82a85fe12eSEd Maste 	style = flags & 0xFFFF;
83a85fe12eSEd Maste 	rc = flags >> 16;
84a85fe12eSEd Maste 
85a85fe12eSEd Maste 	if (mangledname == NULL ||
86a85fe12eSEd Maste 	    ((style = is_mangled(mangledname, style)) == 0)) {
87a85fe12eSEd Maste 		errno = EINVAL;
88a85fe12eSEd Maste 		return (-1);
89a85fe12eSEd Maste 	}
90a85fe12eSEd Maste 
91a85fe12eSEd Maste 	if ((rlt = demangle(mangledname, style, rc)) == NULL) {
92a85fe12eSEd Maste 		errno = EINVAL;
93a85fe12eSEd Maste 		return (-1);
94a85fe12eSEd Maste 	}
95a85fe12eSEd Maste 
96a85fe12eSEd Maste 	if (buffer == NULL || bufsize < strlen(rlt) + 1) {
97a85fe12eSEd Maste 		free(rlt);
98a85fe12eSEd Maste 		errno = ENAMETOOLONG;
99a85fe12eSEd Maste 		return (-1);
100a85fe12eSEd Maste 	}
101a85fe12eSEd Maste 
102a85fe12eSEd Maste 	strncpy(buffer, rlt, bufsize);
103a85fe12eSEd Maste 	buffer[bufsize - 1] = '\0';
104a85fe12eSEd Maste 	free(rlt);
105a85fe12eSEd Maste 
106a85fe12eSEd Maste 	return (0);
107a85fe12eSEd Maste }
108