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 <libelf.h> 33 #include <libelftc.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "_libelftc.h" 38 39 ELFTC_VCSID("$Id: elftc_demangle.c 2065 2011-10-26 15:24:47Z jkoshy $"); 40 41 static int 42 is_mangled(const char *s, int style) 43 { 44 45 switch (style) { 46 case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0); 47 case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0); 48 case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0); 49 } 50 51 /* No style or invalid style spcified, try to guess. */ 52 if (is_cpp_mangled_gnu3(s)) 53 return (ELFTC_DEM_GNU3); 54 if (is_cpp_mangled_gnu2(s)) 55 return (ELFTC_DEM_GNU2); 56 if (is_cpp_mangled_ARM(s)) 57 return (ELFTC_DEM_ARM); 58 59 /* Cannot be demangled. */ 60 return (0); 61 } 62 63 static char * 64 demangle(const char *s, int style, int rc) 65 { 66 67 (void) rc; /* XXX */ 68 switch (style) { 69 case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s)); 70 case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s)); 71 case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s)); 72 default: 73 assert(0); 74 return (NULL); 75 } 76 } 77 78 int 79 elftc_demangle(const char *mangledname, char *buffer, size_t bufsize, 80 unsigned int flags) 81 { 82 int style, rc; 83 char *rlt; 84 85 style = flags & 0xFFFF; 86 rc = flags >> 16; 87 88 if (mangledname == NULL || 89 ((style = is_mangled(mangledname, style)) == 0)) { 90 errno = EINVAL; 91 return (-1); 92 } 93 94 if ((rlt = demangle(mangledname, style, rc)) == NULL) { 95 errno = EINVAL; 96 return (-1); 97 } 98 99 if (buffer == NULL || bufsize < strlen(rlt) + 1) { 100 free(rlt); 101 errno = ENAMETOOLONG; 102 return (-1); 103 } 104 105 strncpy(buffer, rlt, bufsize); 106 buffer[bufsize - 1] = '\0'; 107 free(rlt); 108 109 return (0); 110 } 111