// SPDX-FileCopyrightText: 2009-2020 nibble // SPDX-FileCopyrightText: 2009-2020 pancake // SPDX-FileCopyrightText: 2009-2020 maijin // SPDX-License-Identifier: LGPL-3.0-only #include #include #include #include RZ_LIB_VERSION(rz_parse); static RzParsePlugin *parse_static_plugins[] = { RZ_PARSE_STATIC_PLUGINS }; RZ_API RzParse *rz_parse_new(void) { int i; RzParse *p = RZ_NEW0(RzParse); if (!p) { return NULL; } p->parsers = rz_list_newf(NULL); // memleak if (!p->parsers) { rz_parse_free(p); return NULL; } p->notin_flagspace = NULL; p->flagspace = NULL; p->pseudo = false; p->subrel = false; p->subtail = false; p->minval = 0x100; p->localvar_only = false; for (i = 0; i < RZ_ARRAY_SIZE(parse_static_plugins); i++) { rz_parse_add(p, parse_static_plugins[i]); } return p; } RZ_API void rz_parse_free(RzParse *p) { rz_list_free(p->parsers); free(p); } RZ_API bool rz_parse_add(RzParse *p, RzParsePlugin *foo) { bool itsFine = true; if (foo->init) { itsFine = foo->init(p, p->user); } if (itsFine) { rz_list_append(p->parsers, foo); } return true; } RZ_API bool rz_parse_use(RzParse *p, const char *name) { RzListIter *iter; RzParsePlugin *h; rz_return_val_if_fail(p && name, false); rz_list_foreach (p->parsers, iter, h) { if (!strcmp(h->name, name)) { p->cur = h; return true; } } p->cur = NULL; return false; } // this function is a bit confussing, assembles C code into wat?, whehres theh input and wheres the output // and its unused. so imho it sshould be DEPRECATED this conflicts with rasm.assemble imhoh RZ_API bool rz_parse_assemble(RzParse *p, char *data, char *str) { char *in = strdup(str); bool ret = false; char *s, *o; data[0] = '\0'; if (p->cur && p->cur->assemble) { o = data + strlen(data); do { s = strchr(str, ';'); if (s) { *s = '\0'; } ret = p->cur->assemble(p, o, str); if (!ret) { break; } if (s) { str = s + 1; o += strlen(data); o[0] = '\n'; o[1] = '\0'; o++; } } while (s); } free(in); return ret; } /** * \brief Converts the assembly line into pseudocode * * Converts the assembly line into pseudocode * */ RZ_API char *rz_parse_pseudocode(RzParse *p, const char *assembly) { rz_return_val_if_fail(p, NULL); if (RZ_STR_ISEMPTY(assembly)) { return NULL; } RzStrBuf *sb = rz_strbuf_new(""); if (!sb) { return NULL; } rz_strbuf_reserve(sb, 128); if (!p->cur || !p->cur->parse || !p->cur->parse(p, assembly, sb)) { rz_strbuf_free(sb); return NULL; } return rz_strbuf_drain(sb); } RZ_API char *rz_parse_immtrim(char *opstr) { if (!opstr || !*opstr) { return NULL; } char *n = strstr(opstr, "0x"); if (n) { char *p = n + 2; while (IS_HEXCHAR(*p)) { p++; } memmove(n, p, strlen(p) + 1); } if (strstr(opstr, " - ]")) { opstr = rz_str_replace(opstr, " - ]", "]", 1); } if (strstr(opstr, " + ]")) { opstr = rz_str_replace(opstr, " + ]", "]", 1); } if (strstr(opstr, ", ]")) { opstr = rz_str_replace(opstr, ", ]", "]", 1); } if (strstr(opstr, " - ")) { opstr = rz_str_replace(opstr, " - ", "-", 1); } if (strstr(opstr, " + ")) { opstr = rz_str_replace(opstr, " + ", "+", 1); } return opstr; } /* * \brief Substitutes register relative accesses with function variable names * \param p The parser * \param f The function * \param op The analysis op of the current instruction * \param data The disassembly of the current instruction * \param str The string buffer to write the output to * \param len The length of the string buffer */ RZ_API bool rz_parse_subvar(RzParse *p, RZ_NULLABLE RzAnalysisFunction *f, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL RZ_IN char *data, RZ_BORROW RZ_NONNULL RZ_OUT char *str, int len) { rz_return_val_if_fail(op && data && str, false); if (p->cur && p->cur->subvar) { return p->cur->subvar(p, f, op, data, str, len); } return false; } /* setters */ RZ_API void rz_parse_set_user_ptr(RzParse *p, void *user) { p->user = user; }