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