ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

Select the types of activity you want to include in your feed.

Expand namespace graph emission w semantic call field alias and external relationship edges

+197 -5
+150 -5
src/cf.c
··· 314 314 return 0; 315 315 } 316 316 317 - static char *dot_namespace(const tobi_ns *ns, tobi_graph_labels labels) { 317 + static int ns_index_n(const tobi_ns *ns, const char *path, size_t len, size_t *idx) { 318 + if (!ns || !path) { 319 + return 0; 320 + } 321 + for (size_t i = 0; i < ns->len; i++) { 322 + const char *cur = ns->items[i].path; 323 + if (cur && strlen(cur) == len && strncmp(cur, path, len) == 0) { 324 + *idx = i; 325 + return 1; 326 + } 327 + } 328 + return 0; 329 + } 330 + 331 + static int ns_index_for_ir(const tobi_ns *ns, const tobi_ir *n, tobi_ns_kind kind, size_t *idx) { 332 + if (!ns || !n) { 333 + return 0; 334 + } 335 + if (n->path && ns_index(ns, n->path, idx)) { 336 + return 1; 337 + } 338 + if (!n->name) { 339 + return 0; 340 + } 341 + for (size_t i = 0; i < ns->len; i++) { 342 + const tobi_ns_ent *e = &ns->items[i]; 343 + if (e->kind == kind && e->name && strcmp(e->name, n->name) == 0 && e->off == n->off) { 344 + *idx = i; 345 + return 1; 346 + } 347 + } 348 + return 0; 349 + } 350 + 351 + static void dot_ns_edge(tobi_sb *sb, size_t *edge_next, size_t from, size_t to, const char *style, 352 + const char *label, int constraint, tobi_graph_labels labels) { 353 + const char *edge_style = style && style[0] ? style : "solid"; 354 + if (labels != TOBI_GRAPH_LABEL_NONE && label && label[0]) { 355 + size_t id = (*edge_next)++; 356 + tobi_sb_printf(sb, " r%zu [shape=box,style=\"solid\",", id); 357 + tobi_sb_add(sb, "color=\"#000000\",fontcolor=\"#000000\","); 358 + tobi_sb_add(sb, "fontname=\"Times-Roman\",fontsize=10,margin=\"0.06,0.03\","); 359 + tobi_sb_add(sb, "height=0,width=0,label=\""); 360 + dot_escape(sb, label); 361 + tobi_sb_add(sb, "\"];\n"); 362 + tobi_sb_printf(sb, " n%zu -> r%zu [style=%s,arrowhead=none", from, id, edge_style); 363 + if (!constraint) { 364 + tobi_sb_add(sb, ",constraint=false"); 365 + } 366 + tobi_sb_add(sb, "];\n"); 367 + tobi_sb_printf(sb, " r%zu -> n%zu [style=%s,arrowhead=vee", id, to, edge_style); 368 + if (!constraint) { 369 + tobi_sb_add(sb, ",constraint=false"); 370 + } 371 + tobi_sb_add(sb, "];\n"); 372 + return; 373 + } 374 + tobi_sb_printf(sb, " n%zu -> n%zu [style=%s,arrowhead=vee", from, to, edge_style); 375 + if (!constraint) { 376 + tobi_sb_add(sb, ",constraint=false"); 377 + } 378 + tobi_sb_add(sb, "];\n"); 379 + } 380 + 381 + static int target_ns_index(const tobi_ns *ns, const char *target, const char *key, size_t *idx) { 382 + if (!target || !key) { 383 + return 0; 384 + } 385 + size_t key_len = strlen(key); 386 + const char *p = target; 387 + while ((p = strstr(p, key)) != NULL) { 388 + if (p != target && p[-1] != ' ' && p[-1] != '\t') { 389 + p += key_len; 390 + continue; 391 + } 392 + const char *value = p + key_len; 393 + const char *end = value; 394 + while (*end && *end != ' ' && *end != '\t' && *end != '\n' && *end != '\r') { 395 + end++; 396 + } 397 + if (end > value && ns_index_n(ns, value, (size_t)(end - value), idx)) { 398 + return 1; 399 + } 400 + p = end; 401 + } 402 + return 0; 403 + } 404 + 405 + static void dot_namespace_field_edges(tobi_sb *sb, size_t *edge_next, const tobi_ns *ns, 406 + const tobi_ir *n, tobi_graph_labels labels) { 407 + static const struct { 408 + const char *key; 409 + const char *label; 410 + } rels[] = { 411 + {"region=", "region"}, 412 + {"index=", "index"}, 413 + {"data=", "data"}, 414 + {"bank=", "bank"} 415 + }; 416 + size_t from = 0; 417 + if (!ns_index_for_ir(ns, n, TOBI_NS_FIELD, &from)) { 418 + return; 419 + } 420 + for (size_t i = 0; i < sizeof(rels) / sizeof(rels[0]); i++) { 421 + size_t to = 0; 422 + if (target_ns_index(ns, n->target, rels[i].key, &to)) { 423 + dot_ns_edge(sb, edge_next, from + 1u, to + 1u, "dotted", rels[i].label, 0, labels); 424 + } 425 + } 426 + } 427 + 428 + static void dot_namespace_ir_edges(tobi_sb *sb, size_t *edge_next, const tobi_ir *n, const tobi_ns *ns, 429 + size_t current_method, tobi_graph_labels labels) { 430 + if (!n || !ns) { 431 + return; 432 + } 433 + if (n->kind == TOBI_IR_METHOD && n->path) { 434 + size_t found = 0; 435 + if (ns_index(ns, n->path, &found)) { 436 + current_method = found; 437 + } 438 + } 439 + if (n->kind == TOBI_IR_CALL && current_method != (size_t)-1 && n->path) { 440 + size_t target = 0; 441 + if (ns_index(ns, n->path, &target) && target != current_method) { 442 + dot_ns_edge(sb, edge_next, current_method + 1u, target + 1u, "dashed", "call", 0, labels); 443 + } 444 + } else if (n->kind == TOBI_IR_FIELD_ELEM) { 445 + dot_namespace_field_edges(sb, edge_next, ns, n, labels); 446 + } 447 + for (size_t i = 0; i < n->child_len; i++) { 448 + dot_namespace_ir_edges(sb, edge_next, n->child[i], ns, current_method, labels); 449 + } 450 + } 451 + 452 + static char *dot_namespace(const tobi_ir *root, const tobi_ns *ns, tobi_graph_labels labels) { 318 453 tobi_sb sb; 319 454 tobi_sb_init(&sb); 320 455 tobi_sb_add(&sb, "digraph tobi_namespace {\n"); ··· 363 498 } 364 499 } 365 500 } 366 - tobi_sb_add(&sb, "\"];\n"); 501 + tobi_sb_add(&sb, "\""); 502 + if (e->external || e->kind == TOBI_NS_EXTERNAL) { 503 + tobi_sb_add(&sb, ",style=\"dashed\""); 504 + } 505 + tobi_sb_add(&sb, "];\n"); 367 506 } 507 + size_t edge_next = 0; 368 508 for (size_t i = 0; i < ns->len; i++) { 369 509 const tobi_ns_ent *e = &ns->items[i]; 370 510 size_t parent = 0; ··· 372 512 if (e->owner && ns_index(ns, e->owner, &found)) { 373 513 parent = found + 1u; 374 514 } 375 - tobi_sb_printf(&sb, " n%zu -> n%zu;\n", parent, i + 1u); 515 + if (e->external || e->kind == TOBI_NS_EXTERNAL) { 516 + dot_ns_edge(&sb, &edge_next, parent, i + 1u, "dotted", "external", 1, labels); 517 + } else { 518 + tobi_sb_printf(&sb, " n%zu -> n%zu;\n", parent, i + 1u); 519 + } 376 520 if (e->target && ns_index(ns, e->target, &found)) { 377 - tobi_sb_printf(&sb, " n%zu -> n%zu [style=dashed,arrowhead=vee];\n", i + 1u, found + 1u); 521 + dot_ns_edge(&sb, &edge_next, i + 1u, found + 1u, "dashed", "alias", 0, labels); 378 522 } 379 523 } 524 + dot_namespace_ir_edges(&sb, &edge_next, root, ns, (size_t)-1, labels); 380 525 } 381 526 tobi_sb_add(&sb, "}\n"); 382 527 return tobi_sb_take(&sb); ··· 396 541 case TOBI_GRAPH_AST: 397 542 return dot_ast(root, labels); 398 543 case TOBI_GRAPH_NAMESPACE: 399 - return dot_namespace(ns, labels); 544 + return dot_namespace(root, ns, labels); 400 545 case TOBI_GRAPH_CFG: 401 546 default: 402 547 return dot_cfg(root, labels);
+47
test/t_cf.c
··· 70 70 free(dot); 71 71 tobi_parse_result_free(&r); 72 72 73 + uint8_t ns_call[] = { 74 + 0x14,0x08,'C','A','L','0',0x01,0xa4,0x68, 75 + 0x14,0x0d,'U','S','E','0',0x00,0xa4,'C','A','L','0',0x0a,0x05 76 + }; 77 + T_CHECK(tobi_parse(ns_call, sizeof(ns_call), 0, &r)); 78 + T_CHECK(tobi_cf_recover(r.root, &r.diag)); 79 + dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE); 80 + T_STR(dot, "USE0"); 81 + T_STR(dot, "CAL0"); 82 + T_STR(dot, "call"); 83 + free(dot); 84 + tobi_parse_result_free(&r); 85 + 86 + uint8_t ns_field[] = { 87 + 0x5b,0x80,'R','E','G','0',0x01,0x0a,0x10,0x0a,0x04, 88 + 0x5b,0x81,0x0b,'R','E','G','0',0x00,'F','L','D','0',0x08 89 + }; 90 + T_CHECK(tobi_parse(ns_field, sizeof(ns_field), 0, &r)); 91 + T_CHECK(tobi_cf_recover(r.root, &r.diag)); 92 + dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE); 93 + T_STR(dot, "FLD0"); 94 + T_STR(dot, "REG0"); 95 + T_STR(dot, "region"); 96 + free(dot); 97 + tobi_parse_result_free(&r); 98 + 99 + uint8_t ns_alias[] = { 100 + 0x08,'C','A','L','0',0x01, 101 + 0x06,'C','A','L','0','A','L','S','0' 102 + }; 103 + T_CHECK(tobi_parse(ns_alias, sizeof(ns_alias), 0, &r)); 104 + T_CHECK(tobi_cf_recover(r.root, &r.diag)); 105 + dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE); 106 + T_STR(dot, "ALS0"); 107 + T_STR(dot, "alias"); 108 + free(dot); 109 + tobi_parse_result_free(&r); 110 + 111 + uint8_t ns_external[] = {0x15,'C','A','L','X',0x08,0x01}; 112 + T_CHECK(tobi_parse(ns_external, sizeof(ns_external), 0, &r)); 113 + T_CHECK(tobi_cf_recover(r.root, &r.diag)); 114 + dot = tobi_graph_dot(r.root, &r.ns, TOBI_GRAPH_NAMESPACE); 115 + T_STR(dot, "CALX"); 116 + T_STR(dot, "external"); 117 + free(dot); 118 + tobi_parse_result_free(&r); 119 + 73 120 uint8_t amb[] = {0xa0,0x03,0x01,0xa1}; 74 121 T_CHECK(tobi_parse(amb, sizeof(amb), 0, &r)); 75 122 T_CHECK(r.root->child_len == 1);