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