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