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