char *r_bin_demangle_swift(const char *s, int syscmd) { #define STRCAT_BOUNDS(x) if ((x + 2 + strlen (out)) > sizeof (out)) break; char out[1024]; int i, len, is_generic = 0; int is_first = 1; int is_last = 0; int retmode = 0; if (!strncmp (s, "imp.", 4)) s = s + 4; if (!strncmp (s, "reloc.", 6)) s = s + 6; if (*s != 'T' && strncmp (s, "_T", 2) && strncmp (s, "__T", 3)) { return NULL; } if (!strncmp (s, "__", 2)) s = s + 2; #if 0 const char *element[] = { "module", "class", "method", NULL }; #endif const char *attr = NULL; const char *attr2 = NULL; const char *q, *p = s; const char *q_end = p + strlen (p); if (strchr (s, '\'') || strchr (s, ' ')) { return NULL; } if (syscmd) { char *res = swift_demangle_cmd (s); if (res) { return res; } } out[0] = 0; const char *tail = NULL; if (p[0]) { switch (p[1]) { case 'W': switch (p[2]) { case 'a': tail = "..protocol"; break; } break; case 'F': switch (p[2]) { case 'e': tail = "..extension"; p += 2; break; } break; case 'M': switch (p[2]) { case 'a': tail = "..accessor.metadata"; break; case 'e': tail = "..override"; break; case 'm': tail = "..metaclass"; break; case 'L': tail = "..lazy.metadata"; break; default: tail = "..metadata"; break; } break; case 'I': // interfaces /* TODO */ break; } } p += (tail? 1: 2); // XXX q = getnum (p, NULL); // _TF or __TW if (IS_NUMBER (*p) || *p == 'v' || *p == 'I' || *p == 'o' || *p == 'T' || *p == 'V' || *p == 'M' || *p == 'C' || *p == 'F' || *p == 'W') { if (!strncmp (p+1, "SS", 2)) { strcat (out, "Swift.String.init ("); p += 3; } if (!strncmp (p, "vdv", 3)) { tail = "..field"; p += 3; } if (!strncmp (p, "oFC", 3)) { tail = "..init.witnesstable"; p += 4; } #if 0 if (!strncmp (p+1, "C", 2)) { strcat (out, "class "); p += 3; } #endif q = getnum (q, &len); q = numpos (p); //printf ("(%s)\n", getstring (p, (q-p))); for (i = 0, len = 1; len && q < q_end; q += len, i++) { if (*q == 'P') { // printf ("PUBLIC: "); q++; } q = getnum (q, &len); if (!len) break; const char *str = getstring (q, len); if (len == 2 && !strcmp (str, "ee")) { strcat (out, "Swift"); } else { #if 0 printf ("%s %d %s\n", element[i], len, getstring (q, len)); #endif // push string if (i && *out) strcat (out, "."); STRCAT_BOUNDS (len); len = R_MIN (len, strlen (q)); strcat (out, getstring (q, len)); } } if (q > q_end) { return 0; } p = resolve (flags, q, &attr); if (!p && ((*q == 'U') || (*q == 'R'))) { p = resolve (metas, q, &attr); if (attr && *q == 'R') { attr = NULL; q += 3; //q = p + 1; // //printf ("Template (%s)\n", attr); } else { //printf ("Findus (%s)\n", q); } // return 0; } /* parse accessors */ if (attr) { int len = 0; const char *name; /* get field name and then type */ resolve (types, q, &attr); //printf ("Accessor: %s\n", attr); q = getnum (q + 1, &len); name = getstring (q, len); #if 0 if (name && *name) { printf ("Field Name: %s\n", name); } #endif if (len < strlen (q)) { resolve (types, q + len, &attr2); } else { resolve (types, q, &attr2); } // printf ("Field Type: %s\n", attr2); do { if (name && *name) { strcat (out, "."); STRCAT_BOUNDS (strlen (name)); strcat (out, name); } if (attr && *attr) { strcat (out, "."); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } if (attr2 && *attr2) { strcat (out, "__"); STRCAT_BOUNDS (strlen (attr2)); strcat (out, attr2); } } while (0); if (q && *q == '_') { strcat (out, " -> ()"); } } else { /* parse function parameters here */ // type len value/ for (i = 0; q && q < q_end; i++) { if (*q == 'f') { q++; } switch (*q) { case 's': { int n; const char *Q = getnum (q + 1, &n); strcat (out, getstring (Q, n)); q = Q + n + 1; continue; } break; case 'u': if (!strncmp (q, "uRxs", 4)) { strcat (out, ".."); int n; const char *Q = getnum (q + 4, &n); strcat (out, getstring (Q, n)); q = Q + n + 1; continue; } break; case 'S': // "S0" if (q[1]=='1') q++; switch (q[1]) { case '0': strcat (out, " (self) -> ()"); if (attr) { strcat (out, attr); } //p = q + 7; q = p = q + 1; attr = ""; break; case 'S': // swift string strcat (out, "__String"); break; case '_': // swift string { strcat (out, ".."); int n; const char *Q = getnum (q + 2, &n); strcat (out, getstring (Q, n)); q = Q + n + 1; } continue; break; } break; case 'B': case 'T': case 'I': p = resolve (types, q + 0, &attr); // type if (p && *p && IS_NUMBER (p[1])) { p--; } break; case 'F': strcat (out, " ()"); p = resolve (types, q + 3, &attr); // type break; case 'G': q += 2; //printf ("GENERIC\n"); if (!strncmp (q, "_V", 2)) { q += 2; } p = resolve (types, q, &attr); // type break; case 'V': p = resolve (types, q + 1, &attr); // type break; case '_': // it's return value time! p = resolve (types, q+1, &attr); // type //printf ("RETURN TYPE %s\n", attr); break; default: p = resolve (types, q, &attr); // type } if (p) { q = p; q = getnum (p, &len); if (attr && !strcmp (attr, "generic")) is_generic = 1; //printf ("TYPE: %s LEN %d VALUE %s\n", // attr, len, getstring (q, len)); if (!len) { if (retmode) { if (q + 1 > q_end) { if (attr) { strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } break; } p = resolve (types, q + 1, &attr); // type //printf ("RETURN TYPE %s\n", attr); // printf ("RET %s\n", attr); if (attr) { strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } break; } retmode = 1; len++; } if (len <= (q_end-q) && q[len]) { const char *s = getstring (q, len); if (s && *s) { if (is_first) { strcat (out, is_generic?"<":"("); is_first = 0; } //printf ("ISLAST (%s)\n", q+len); is_last = q[len]; if (attr) { STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); strcat (out, " "); } STRCAT_BOUNDS (strlen (s)); strcat (out, s); if (is_last) { strcat (out, is_generic?">":")"); is_first = (*s != '_'); if (is_generic && !is_first) { break; } } else { strcat (out, ", "); } } else { if (attr) { strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } } } else { if (attr) { strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } } q += len; p = q; } else { if (q) { q++; } else { break; } char *n = strstr (q, "__"); if (n) { q = n + 1; } else { n = strstr (q, "_"); if (n) { q = n + 1; } else { break; } } } } } } else { //printf ("Unsupported type: %c\n", *p); } if (*out) { if (tail) strcat (out, tail); #if 1 char *p, *outstr = strdup (out); p = outstr; for (;;) { p = strstr (p, ")("); if (p) { p[0] = '_'; p[1] = '_'; p+=2; } else break; } return outstr; #endif } return NULL; }
char *r_bin_demangle_swift(const char *s) { #define STRCAT_BOUNDS(x) if ((x+2+strlen (out))>sizeof (out)) break; static char *swift_demangle = NULL; char out[8192]; int i, len, is_generic = 0;; int is_first = 1; int is_last = 0; int retmode = 0; if (!strncmp (s, "__", 2)) s = s + 2; if (!strncmp (s, "imp.", 4)) s = s + 4; if (!strncmp (s, "reloc.", 6)) s = s + 6; #if 0 const char *element[] = { "module", "class", "method", NULL }; #endif const char *attr = NULL; const char *attr2 = NULL; const char *q, *p = s; if (strncmp (s, "_T", 2)) { return NULL; } if (strchr (s, '\'') || strchr (s, ' ')) return NULL; if (!swift_demangle) { swift_demangle = r_file_path ("swift-demangle"); if (!swift_demangle || !strcmp (swift_demangle, "swift-demangle")) { char *xcrun = r_file_path ("xcrun"); if (xcrun) { free (swift_demangle); swift_demangle = r_str_newf ("%s swift-demangle", xcrun); free (xcrun); } } } if (swift_demangle) { char *res = r_sys_cmd_strf ("%s -compact -simplified '%s'", swift_demangle, s); if (res && !*res) { free (res); res = NULL; } return r_str_chop (res); } out[0] = 0; p += 2; if (*p == 'F' || *p == 'W') { q = numpos (p); //printf ("(%s)\n", getstring (p, (q-p))); for (i=0, len = 1; len; q += len, i++) { if (*q=='P') { // printf ("PUBLIC: "); q++; } q = getnum (q, &len); if (!len) break; #if 0 printf ("%s %d %s\n", element[i], len, getstring (q, len)); #endif // push string if (*out) strcat (out, "."); STRCAT_BOUNDS (len); strcat (out, getstring (q, len)); } p = resolve (flags, q, &attr); if (!p && *q=='U') { p = resolve (metas, q, &attr); if (attr) { //printf ("Template (%s)\n", attr); } else { //printf ("Findus (%s)\n", q); } // return 0; } if (attr) { int len; const char *name; /* get field name and then type */ resolve (types, q, &attr); //printf ("Accessor: %s\n", attr); q = getnum (q+1, &len); name = getstring (q, len); #if 0 if (name && *name) { printf ("Field Name: %s\n", name); } #endif resolve (types, q+len, &attr2); // printf ("Field Type: %s\n", attr2); do { if (name && *name) { strcat (out, "."); STRCAT_BOUNDS (strlen (name)); strcat (out, name); } if (attr && *attr) { strcat (out, "."); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } if (attr2 && *attr2) { strcat (out, "__"); STRCAT_BOUNDS (strlen (attr2)); strcat (out, attr2); } } while (0); } else { /* parse function parameters here */ // type len value for (i=0; q; i++) { switch (*q) { case 'B': case 'T': case 'I': case 'F': p = resolve (types, q+3, &attr); // type break; case 'G': q+=2; //printf ("GENERIC\n"); if (!strncmp (q, "_V", 2)) { q+=2; } p = resolve (types, q, &attr); // type break; case 'V': // printf ("VECTOR\n"); p = resolve (types, q+1, &attr); // type break; case '_': // it's return value time! p = resolve (types, q+1, &attr); // type //printf ("RETURN TYPE %s\n", attr); break; default: p = resolve (types, q, &attr); // type } if (p) { q = p; q = getnum (p, &len); if (!strcmp (attr, "generic")) is_generic = 1; //printf ("TYPE: %s LEN %d VALUE %s\n", // attr, len, getstring (q, len)); if (!len) { if (retmode) { p = resolve (types, q+1, &attr); // type //printf ("RETURN TYPE %s\n", attr); // printf ("RET %s\n", attr); strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); break; } retmode = 1; len++; } if (q[len]) { const char *s = getstring (q, len); if (s && *s) { if (is_first) { strcat (out, is_generic?"<":"("); is_first = 0; } //printf ("ISLAST (%s)\n", q+len); is_last = q[len]; STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); strcat (out, " "); STRCAT_BOUNDS (strlen (s)); strcat (out, s); if (is_last) { strcat (out, is_generic?">":")"); is_first = 1; } else { strcat (out, ", "); } } else { strcat (out, " -> "); STRCAT_BOUNDS (strlen (attr)); strcat (out, attr); } } else { } q += len; } else { //printf ("void\n"); q++; break; } } } } else { //printf ("Unsupported type: %c\n", *p); } if (*out) { char *p, *outstr = strdup (out); p = outstr; for (;;) { p = strstr (p, ")("); if (p) { p[0] = '_'; p[1] = '_'; p+=2; } else break; } return outstr; } return NULL; }