1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright (c) 1998 by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #include <ctype.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include "elf_dem.h" 35 #include "String.h" 36 #include "msg.h" 37 38 /* This structure is used to keep 39 * track of pointers to argument 40 * descriptions in the mangled string. 41 * This is needed for N and T encodings 42 * to work. 43 */ 44 typedef struct { 45 char *list[10]; 46 int pos; 47 } Place; 48 49 static Place here; 50 51 /* Strings and flags needed by the argument demangles. The declarator 52 * is built up in ptr. Type modifiers are held in the flag fields. 53 * The type itself is passed in separately. 54 */ 55 typedef struct { 56 String *ptr; 57 int Sign,Uns,Cons,Vol; 58 } Arg_Remem; 59 60 /* initialize Arg_Remem */ 61 static void 62 mkar(Arg_Remem *r) 63 { 64 r->ptr = mk_String((String *)0); 65 r->Sign = r->Uns = r->Cons = r->Vol = 0; 66 } 67 68 /* free data for Arg_Remem */ 69 static void 70 delar(Arg_Remem *r) 71 { 72 free_String(r->ptr); 73 } 74 75 /* This routine formats a single argument 76 * on the buffer sptr. 77 * c is the type or class name, n is its length. 78 */ 79 static void 80 nsetarg(String ** sptr, Arg_Remem * r, const char * c, int n) 81 { 82 r->ptr = nprep_String(c, r->ptr, n); 83 if(r->Cons) 84 r->ptr = prep_String(MSG_ORIG(MSG_STR_CONST_1), r->ptr); 85 if(r->Vol) 86 r->ptr = prep_String(MSG_ORIG(MSG_STR_VOLATILE_1), r->ptr); 87 if(r->Uns) 88 r->ptr = prep_String(MSG_ORIG(MSG_STR_UNSIGNED), r->ptr); 89 else if(r->Sign) 90 r->ptr = prep_String(MSG_ORIG(MSG_STR_SIGNED), r->ptr); 91 *sptr = app_String(*sptr,PTR(r->ptr)); 92 delar(r); 93 } 94 95 /* This routine formats a single argument 96 * on the buffer sptr. 97 * c is the null terminated type or class name. 98 */ 99 static void 100 setarg(String ** sptr, Arg_Remem * r, const char * c) 101 { 102 nsetarg(sptr, r, c, ID_NAME_MAX); 103 } 104 105 106 /* Demangle a single function argument. 107 * Returns the number of characters processed from c. 108 */ 109 int 110 demangle_doarg(String **sptr, char *c) 111 { 112 int i; 113 Arg_Remem ar; 114 mkar(&ar); 115 116 if(here.pos < 10 && here.pos >= 0) 117 here.list[here.pos++] = c; 118 119 for(i=0;c[i];i++) { 120 /* Loop until you find a type. 121 Then call setarg and return. 122 */ 123 switch(c[i]) { 124 125 case 'T': 126 { 127 Place tmp; 128 tmp = here; 129 here.pos = c[1] - '1'; 130 if(here.pos < 0 || here.pos >= tmp.pos-1) { 131 delar(&ar); 132 return -1; 133 } 134 (void) demangle_doarg(sptr,here.list[here.pos]); 135 here = tmp; 136 delar(&ar); 137 return 2; 138 } 139 case 'N': 140 { 141 Place tmp; 142 int cycles,pos; 143 cycles = c[1] - '0'; pos = c[2] - '1'; 144 here.pos += cycles - 1; 145 tmp = here; 146 if(cycles <= 1 || cycles > 9 || pos < 0 || pos >= tmp.pos-1) { 147 delar(&ar); 148 return -1; 149 } 150 while(cycles--) { 151 here = tmp; 152 here.pos = pos; 153 (void) demangle_doarg(sptr,here.list[here.pos]); 154 (*sptr) = app_String(*sptr, 155 MSG_ORIG(MSG_STR_COMMA)); 156 } 157 *sptr = trunc_String(*sptr, 1); 158 here = tmp; 159 delar(&ar); 160 return 3; 161 } 162 163 /* Qualifiers to type names */ 164 case 'S': 165 ar.Sign = 1; 166 break; 167 case 'U': 168 ar.Uns = 1; 169 break; 170 case 'C': 171 ar.Cons = 1; 172 break; 173 case 'V': 174 ar.Vol = 1; 175 break; 176 177 /* Pointers, references, and Member Pointers */ 178 case 'P': 179 case 'R': 180 case 'M': 181 if(ar.Cons) { 182 ar.ptr = prep_String(MSG_ORIG(MSG_STR_CONST_2), 183 ar.ptr); 184 ar.Cons = 0; 185 } 186 if(ar.Vol) { 187 ar.ptr = 188 prep_String(MSG_ORIG(MSG_STR_VOLATILE_2), 189 ar.ptr); 190 ar.Vol = 0; 191 } 192 if(c[i] == 'P') 193 ar.ptr = prep_String(MSG_ORIG(MSG_STR_STAR), 194 ar.ptr); 195 else if(c[i] == 'R') 196 ar.ptr = prep_String(MSG_ORIG(MSG_STR_AMP), 197 ar.ptr); 198 else { 199 int cnt = 0; 200 char *s; 201 ar.ptr = 202 prep_String(MSG_ORIG(MSG_STR_DBLCOLSTAR), 203 ar.ptr); 204 /* Skip over the 'M' */ 205 i++; 206 cnt = strtol(c+i, &s, 10); 207 i = s - c; 208 ar.ptr = nprep_String(c+i,ar.ptr,cnt); 209 ar.ptr = prep_String(MSG_ORIG(MSG_STR_SPACE), 210 ar.ptr); 211 i += cnt; 212 /* The loop increments i */ 213 i--; 214 } 215 break; 216 217 /* Demangle for basic built-in types */ 218 case 'i': 219 setarg(sptr, &ar, MSG_ORIG(MSG_STR_INT)); 220 return i + 1; 221 case 'c': 222 setarg(sptr, &ar, MSG_ORIG(MSG_STR_CHAR)); 223 return i + 1; 224 case 's': 225 setarg(sptr, &ar, MSG_ORIG(MSG_STR_SHORT)); 226 return i + 1; 227 case 'l': 228 setarg(sptr, &ar, MSG_ORIG(MSG_STR_LONG)); 229 return i + 1; 230 case 'f': 231 setarg(sptr, &ar, MSG_ORIG(MSG_STR_FLOAT)); 232 return i + 1; 233 case 'd': 234 setarg(sptr, &ar, MSG_ORIG(MSG_STR_DOUBLE)); 235 return i + 1; 236 case 'r': 237 setarg(sptr, &ar, MSG_ORIG(MSG_STR_LONGDOUBLE)); 238 return i + 1; 239 240 /* Class encodings */ 241 case '1': case '2': case '3': 242 case '4': case '5': case '6': 243 case '7': case '8': case '9': 244 { 245 int cnt = 0; 246 char *s; 247 cnt = strtol(c+i, &s, 10); 248 i = s - c; 249 if ((int) strlen(c+i) < cnt) { 250 delar(&ar); 251 return -1; 252 } 253 nsetarg(sptr,&ar,c+i,cnt); 254 return i+cnt; 255 } 256 257 /* Ellipsis and void */ 258 case 'e': 259 setarg(sptr, &ar, MSG_ORIG(MSG_STR_ELIPSE)); 260 return i + 1; 261 case 'v': 262 setarg(sptr, &ar, MSG_ORIG(MSG_STR_VOID)); 263 return i + 1; 264 265 /* Arrays */ 266 case 'A': 267 if(*PTR(ar.ptr)) { 268 ar.ptr = prep_String(MSG_ORIG(MSG_STR_OPENPAR), 269 ar.ptr); 270 ar.ptr = app_String(ar.ptr, 271 MSG_ORIG(MSG_STR_CLOSEPAR)); 272 } 273 ar.ptr = app_String(ar.ptr, MSG_ORIG(MSG_STR_OPENBRAK)); 274 { 275 int cnt = 0; 276 i++; 277 while(isdigit(c[i+cnt])) 278 cnt++; 279 ar.ptr = napp_String(ar.ptr,c+i,cnt); 280 i += cnt; 281 if(c[i] != '_') { 282 delar(&ar); 283 return -1; 284 } 285 } 286 ar.ptr = app_String(ar.ptr, 287 MSG_ORIG(MSG_STR_CLOSEBRAK)); 288 break; 289 290 /* Functions 291 * This will always be called as a pointer 292 * to a function. 293 */ 294 case 'F': 295 ar.ptr = prep_String(MSG_ORIG(MSG_STR_OPENPAR), ar.ptr); 296 ar.ptr = app_String(ar.ptr, MSG_ORIG(MSG_STR_CLOSEPAR)); 297 { 298 Place tmp; 299 tmp = here; 300 i++; 301 i += demangle_doargs(&ar.ptr,c+i); 302 if(c[i] != '_') { 303 delar(&ar); 304 return -1; 305 } 306 here = tmp; 307 } 308 break; 309 310 /* Needed when this is called to demangle 311 * an argument of a pointer to a function. 312 */ 313 case '_': 314 delar(&ar); 315 return 0; 316 317 default: 318 delar(&ar); 319 return -1; 320 } 321 } 322 323 /* Did the argument list terminate properly? */ 324 { 325 int rc = 0; 326 if(*PTR(ar.ptr) || ar.Uns || ar.Sign || ar.Cons || ar.Vol) 327 rc = -1; 328 delar(&ar); 329 return rc; 330 } 331 } 332 333 /* This function is called to demangle 334 * an argument list. 335 * Returns the number of characters processed from c. 336 */ 337 int 338 demangle_doargs(String **sptr, char *c) 339 { 340 int i = 0, n = 0; 341 here.pos = 0; 342 343 *sptr = app_String(*sptr,MSG_ORIG(MSG_STR_OPENPAR)); 344 while (*c && (i = demangle_doarg(sptr,c)) > 0) { 345 c += i; 346 n += i; 347 (*sptr) = app_String(*sptr,(*c && *c == 'e') ? 348 MSG_ORIG(MSG_STR_SPACE) : MSG_ORIG(MSG_STR_COMMA)); 349 } 350 351 if(i < 0) 352 return -1; 353 354 *sptr = app_String(trunc_String(*sptr, 1), MSG_ORIG(MSG_STR_CLOSEPAR)); 355 356 return n; 357 } 358