static char *swift_demangle_cmd(const char *s) { /* XXX: command injection issue here */ static char *swift_demangle = NULL; if (have_swift_demangle == -1) { if (!swift_demangle) { have_swift_demangle = 0; swift_demangle = r_file_path ("swift-demangle"); if (!swift_demangle || !strcmp (swift_demangle, "swift-demangle")) { char *xcrun = r_file_path ("xcrun"); if (xcrun) { if (strcmp (xcrun, "xcrun")) { free (swift_demangle); swift_demangle = r_str_newf ("%s swift-demangle", xcrun); have_swift_demangle = 1; } free (xcrun); } } } } if (swift_demangle) { if (strstr (s, "'") || strstr (s, "\\")) { /* nice try */ return NULL; } //char *res = r_sys_cmd_strf ("%s -compact -simplified '%s'", char *res = r_sys_cmd_strf ("%s -compact '%s'", swift_demangle, s); if (res && !*res) { free (res); res = NULL; } return r_str_chop (res); } return NULL; }
static struct cEnv_t* r_egg_Cfile_set_cEnv(const char *arch, const char *os, int bits) { struct cEnv_t *cEnv = calloc (1, sizeof (struct cEnv_t)); bool use_clang; char *buffer = NULL; char *output = NULL; if (!cEnv) { return NULL; } if (!(cEnv->CC = r_egg_Cfile_getCompiler())) { goto fail; } cEnv->SFLIBPATH = r_sys_getenv ("SFLIBPATH"); if (!cEnv->SFLIBPATH) { output = r_sys_cmd_strf ("r2 -hh | grep INCDIR | awk '{print $2}'"); if (!output || (output[0] == '\0')) { eprintf ("Cannot find SFLIBPATH env var.\n" "Please define it, or fix r2 installation.\n"); goto fail; } output[strlen (output) - 1] = '\0'; // strip the ending '\n' if (!(cEnv->SFLIBPATH = r_str_newf ("%s/sflib", output))) { goto fail; } } cEnv->JMP = r_egg_Cfile_armOrMips (arch) ? "b" : "jmp"; if (!strcmp (os, "darwin")) { cEnv->OBJCOPY = "gobjcopy"; cEnv->FMT = "mach0"; if (!strcmp (arch, "x86")) { if (bits == 32) { cEnv->CFLAGS = strdup ("-arch i386"); cEnv->LDFLAGS = strdup ("-arch i386 -shared -c"); } else { cEnv->CFLAGS = strdup ("-arch x86_64"); cEnv->LDFLAGS = strdup ("-arch x86_64 -shared -c"); } } else { cEnv->LDFLAGS = strdup ("-shared -c"); } cEnv->SHDR = r_str_newf ("\n.text\n%s _main\n", cEnv->JMP); } else { cEnv->OBJCOPY = "objcopy"; cEnv->FMT = "elf"; cEnv->SHDR = r_str_newf ("\n.section .text\n.globl main\n" "// .type main, @function\n%s main\n", cEnv->JMP); if (!strcmp (arch, "x86")) { if (bits == 32) { cEnv->CFLAGS = strdup ("-fPIC -fPIE -pie -fpic -m32"); cEnv->LDFLAGS = strdup ("-fPIC -fPIE -pie -fpic -m32"); } else { cEnv->CFLAGS = strdup ("-fPIC -fPIE -pie -fpic -m64"); cEnv->LDFLAGS = strdup ("-fPIC -fPIE -pie -fpic -m64"); } } else { cEnv->CFLAGS = strdup ("-fPIC -fPIE -pie -fpic -nostartfiles"); cEnv->LDFLAGS = strdup ("-fPIC -fPIE -pie -fpic -nostartfiles"); } } cEnv->TRIPLET = r_str_newf ("%s-%s-%d", os, arch, bits); if (!strcmp (os, "windows")) { cEnv->TEXT = ".text"; cEnv->FMT = "pe"; } else if (!strcmp (os, "darwin")) { cEnv->TEXT = "0.__TEXT.__text"; } else { cEnv->TEXT = ".text"; } use_clang = false; if (!strcmp (cEnv->TRIPLET, "darwin-arm-64")) { free (cEnv->CC); cEnv->CC = strdup ("xcrun --sdk iphoneos gcc -arch arm64 -miphoneos-version-min=0.0"); use_clang = true; cEnv->TEXT = "0.__TEXT.__text"; } else if (!strcmp (cEnv->TRIPLET, "darwin-arm-32")) { free (cEnv->CC); cEnv->CC = strdup ("xcrun --sdk iphoneos gcc -arch armv7 -miphoneos-version-min=0.0"); use_clang = true; cEnv->TEXT = "0.__TEXT.__text"; } buffer = r_str_newf ("%s -nostdinc -include '%s'/'%s'/sflib.h", cEnv->CFLAGS, cEnv->SFLIBPATH, cEnv->TRIPLET); if (!buffer) { goto fail; } free (cEnv->CFLAGS); cEnv->CFLAGS = strdup (buffer); if (use_clang) { free (buffer); buffer = r_str_newf ("%s -fomit-frame-pointer" " -fno-zero-initialized-in-bss", cEnv->CFLAGS); if (!buffer) { goto fail; } free (cEnv->CFLAGS); cEnv->CFLAGS = strdup (buffer); } else { free (buffer); buffer = r_str_newf ("%s -z execstack -fomit-frame-pointer" " -finline-functions -fno-zero-initialized-in-bss", cEnv->CFLAGS); if (!buffer) { goto fail; } free (cEnv->CFLAGS); cEnv->CFLAGS = strdup (buffer); } free (buffer); buffer = r_str_newf ("%s -nostdlib", cEnv->LDFLAGS); if (!buffer) { goto fail; } free (cEnv->LDFLAGS); cEnv->LDFLAGS = strdup (buffer); if (r_egg_Cfile_check_cEnv (cEnv)) { eprintf ("Error with cEnv allocation!\n"); goto fail; } free (buffer); free (output); return cEnv; fail: free (buffer); free (output); r_egg_Cfile_free_cEnv (cEnv); 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; }
R_API char* r_egg_Cfile_parser(const char *file, const char *arch, const char *os, int bits) { char *output = NULL; char *fileExt = NULL; // "file" with extension (.s, .text, ...) struct cEnv_t *cEnv = r_egg_Cfile_set_cEnv (arch, os, bits); if (!cEnv) { goto fail; } r_str_sanitize (cEnv->CC); //printf ("==> Compile\n"); printf ("'%s' %s -o '%s.tmp' -S -Os '%s'\n", cEnv->CC, cEnv->CFLAGS, file, file); output = r_sys_cmd_strf ("('%s' %s -o '%s.tmp' -S -Os '%s') 2>&1", cEnv->CC, cEnv->CFLAGS, file, file); if (output == NULL) { eprintf ("Compilation failed!\n"); goto fail; } printf ("%s", output); if (!(fileExt = r_str_newf ("%s.s", file))) { goto fail; } if (!r_file_dump (fileExt, (const ut8*) cEnv->SHDR, strlen (cEnv->SHDR), false)) { eprintf ("Error while opening %s.s\n", file); goto fail; } if (!r_egg_Cfile_parseCompiled (file)) { goto fail; } //printf ("==> Assemble\n"); printf ("'%s' %s -Os -o '%s.o' '%s.s'\n", cEnv->CC, cEnv->LDFLAGS, file, file); free (output); output = r_sys_cmd_strf ("'%s' %s -Os -o '%s.o' '%s.s'", cEnv->CC, cEnv->LDFLAGS, file, file); if (!output) { eprintf ("Assembly failed!\n"); goto fail; } printf ("%s", output); //printf ("==> Link\n"); printf ("rabin2 -o '%s.text' -O d/S/'%s' '%s.o'\n", file, cEnv->TEXT, file); free (output); output = r_sys_cmd_strf ("rabin2 -o '%s.text' -O d/S/'%s' '%s'.o", file, cEnv->TEXT, file); if (!output) { eprintf ("Linkage failed!\n"); goto fail; } free (fileExt); if (!(fileExt = r_str_newf ("%s.o", file))) { goto fail; } if (!r_file_exists (fileExt)) { eprintf ("Cannot find %s.o\n", file); goto fail; } free (fileExt); if (!(fileExt = r_str_newf ("%s.text", file))) { goto fail; } if (r_file_size (fileExt) == 0) { printf ("FALLBACK: Using objcopy instead of rabin2"); free (output); output = r_sys_cmd_strf ("'%s' -j .text -O binary '%s.o' '%s.text'", cEnv->OBJCOPY, file, file); if (!output) { eprintf ("objcopy failed!\n"); goto fail; } } size_t i; const char *extArray[] = {"bin", "tmp", "s", "o"}; for (i = 0; i < 4; i++) { free (fileExt); if (!(fileExt = r_str_newf ("%s.%s", file, extArray[i]))) { goto fail; } r_file_rm (fileExt); } free (fileExt); if ((fileExt = r_str_newf ("%s.text", file)) == NULL) { goto fail; } free (output); r_egg_Cfile_free_cEnv (cEnv); return fileExt; fail: free (fileExt); free (output); r_egg_Cfile_free_cEnv (cEnv); return NULL; }