ACPI AML decompiler w/ CFG recovery and structured pseudocode
29

Configure Feed

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

tobi / src / nm.c
11 kB 410 lines
1#include "nm.h" 2 3#include "mem.h" 4#include "str.h" 5 6#include <ctype.h> 7#include <stdlib.h> 8#include <string.h> 9 10int tobi_nm_is_lead(unsigned char c) { 11 return (c >= 'A' && c <= 'Z') || c == '_'; 12} 13 14int tobi_nm_is_tail(unsigned char c) { 15 return tobi_nm_is_lead(c) || (c >= '0' && c <= '9'); 16} 17 18int tobi_nm_nameseg(tobi_rd *rd, char **out) { 19 size_t start = rd->pos; 20 uint8_t b[4]; 21 if (!tobi_rd_bytes(rd, b, sizeof(b))) { 22 rd->pos = start; 23 return 0; 24 } 25 if (!tobi_nm_is_lead(b[0])) { 26 rd->pos = start; 27 rd->failed = 1; 28 return 0; 29 } 30 for (size_t i = 1; i < 4; i++) { 31 if (!tobi_nm_is_tail(b[i])) { 32 rd->pos = start; 33 rd->failed = 1; 34 return 0; 35 } 36 } 37 *out = tobi_xstrndup((const char *)b, 4); 38 return 1; 39} 40 41static void add_seg(tobi_sb *sb, const char *seg, int *first) { 42 if (!*first && sb->len > 0 && sb->buf[sb->len - 1] != '\\' && sb->buf[sb->len - 1] != '^') { 43 tobi_sb_ch(sb, '.'); 44 } 45 tobi_sb_add(sb, seg); 46 *first = 0; 47} 48 49int tobi_nm_namestring(tobi_rd *rd, char **out) { 50 size_t start = rd->pos; 51 tobi_sb sb; 52 tobi_sb_init(&sb); 53 uint8_t b = 0; 54 int first = 1; 55 if (!tobi_rd_peek(rd, &b)) { 56 tobi_sb_free(&sb); 57 return 0; 58 } 59 if (b == '\\') { 60 (void)tobi_rd_u8(rd, &b); 61 tobi_sb_ch(&sb, '\\'); 62 } else { 63 while (tobi_rd_peek(rd, &b) && b == '^') { 64 (void)tobi_rd_u8(rd, &b); 65 tobi_sb_ch(&sb, '^'); 66 } 67 } 68 if (!tobi_rd_peek(rd, &b)) { 69 tobi_sb_free(&sb); 70 rd->pos = start; 71 return 0; 72 } 73 if (b == 0x00) { 74 (void)tobi_rd_u8(rd, &b); 75 if (sb.len == 0) { 76 tobi_sb_add(&sb, "<null>"); 77 } 78 *out = tobi_sb_take(&sb); 79 return 1; 80 } 81 if (b == 0x2e) { 82 (void)tobi_rd_u8(rd, &b); 83 for (int i = 0; i < 2; i++) { 84 char *seg = NULL; 85 if (!tobi_nm_nameseg(rd, &seg)) { 86 tobi_sb_free(&sb); 87 rd->pos = start; 88 return 0; 89 } 90 add_seg(&sb, seg, &first); 91 free(seg); 92 } 93 *out = tobi_sb_take(&sb); 94 return 1; 95 } 96 if (b == 0x2f) { 97 (void)tobi_rd_u8(rd, &b); 98 uint8_t count = 0; 99 if (!tobi_rd_u8(rd, &count) || count == 0) { 100 tobi_sb_free(&sb); 101 rd->pos = start; 102 rd->failed = 1; 103 return 0; 104 } 105 for (uint8_t i = 0; i < count; i++) { 106 char *seg = NULL; 107 if (!tobi_nm_nameseg(rd, &seg)) { 108 tobi_sb_free(&sb); 109 rd->pos = start; 110 return 0; 111 } 112 add_seg(&sb, seg, &first); 113 free(seg); 114 } 115 *out = tobi_sb_take(&sb); 116 return 1; 117 } 118 char *seg = NULL; 119 if (!tobi_nm_nameseg(rd, &seg)) { 120 tobi_sb_free(&sb); 121 rd->pos = start; 122 return 0; 123 } 124 add_seg(&sb, seg, &first); 125 free(seg); 126 *out = tobi_sb_take(&sb); 127 return 1; 128} 129 130static char *pop_scope(const char *scope) { 131 if (!scope || strcmp(scope, "\\") == 0 || scope[0] == '\0') { 132 return tobi_xstrdup("\\"); 133 } 134 const char *last = strrchr(scope, '.'); 135 if (!last) { 136 return tobi_xstrdup("\\"); 137 } 138 return tobi_xstrndup(scope, (size_t)(last - scope)); 139} 140 141char *tobi_nm_resolve(const char *scope, const char *name) { 142 if (!name || name[0] == '\0') { 143 return tobi_xstrdup(scope && scope[0] ? scope : "\\"); 144 } 145 if (name[0] == '\\') { 146 return tobi_xstrdup(name); 147 } 148 char *cur = tobi_xstrdup(scope && scope[0] ? scope : "\\"); 149 const char *rest = name; 150 while (*rest == '^') { 151 char *p = pop_scope(cur); 152 free(cur); 153 cur = p; 154 rest++; 155 } 156 if (*rest == '\0' || strcmp(rest, "<null>") == 0) { 157 return cur; 158 } 159 tobi_sb sb; 160 tobi_sb_init(&sb); 161 if (strcmp(cur, "\\") == 0) { 162 tobi_sb_add(&sb, "\\"); 163 tobi_sb_add(&sb, rest); 164 } else { 165 tobi_sb_add(&sb, cur); 166 tobi_sb_ch(&sb, '.'); 167 tobi_sb_add(&sb, rest); 168 } 169 free(cur); 170 return tobi_sb_take(&sb); 171} 172 173void tobi_ns_init(tobi_ns *ns) { 174 ns->items = NULL; 175 ns->len = 0; 176 ns->cap = 0; 177} 178 179static void ns_ent_free(tobi_ns_ent *e) { 180 free(e->path); 181 free(e->name); 182 free(e->owner); 183 free(e->target); 184} 185 186void tobi_ns_free(tobi_ns *ns) { 187 if (!ns) { 188 return; 189 } 190 for (size_t i = 0; i < ns->len; i++) { 191 ns_ent_free(&ns->items[i]); 192 } 193 free(ns->items); 194 ns->items = NULL; 195 ns->len = 0; 196 ns->cap = 0; 197} 198 199const char *tobi_ns_kind_name(tobi_ns_kind kind) { 200 switch (kind) { 201 case TOBI_NS_UNKNOWN: return "unknown"; 202 case TOBI_NS_SCOPE: return "scope"; 203 case TOBI_NS_DEVICE: return "device"; 204 case TOBI_NS_METHOD: return "method"; 205 case TOBI_NS_PROCESSOR: return "processor"; 206 case TOBI_NS_NAME: return "name"; 207 case TOBI_NS_ALIAS: return "alias"; 208 case TOBI_NS_OPREGION: return "opregion"; 209 case TOBI_NS_FIELD: return "field"; 210 case TOBI_NS_MUTEX: return "mutex"; 211 case TOBI_NS_EVENT: return "event"; 212 case TOBI_NS_EXTERNAL: return "external"; 213 } 214 return "invalid"; 215} 216 217const char *tobi_ns_leaf(const char *path) { 218 if (!path || path[0] == '\0') { 219 return ""; 220 } 221 const char *dot = strrchr(path, '.'); 222 if (dot && dot[1]) { 223 return dot + 1; 224 } 225 if (path[0] == '\\') { 226 return path + 1; 227 } 228 return path; 229} 230 231tobi_ns_ent *tobi_ns_find(tobi_ns *ns, const char *path) { 232 if (!ns || !path) { 233 return NULL; 234 } 235 for (size_t i = 0; i < ns->len; i++) { 236 if (strcmp(ns->items[i].path, path) == 0) { 237 return &ns->items[i]; 238 } 239 } 240 return NULL; 241} 242 243const tobi_ns_ent *tobi_ns_find_const(const tobi_ns *ns, const char *path) { 244 if (!ns || !path) { 245 return NULL; 246 } 247 for (size_t i = 0; i < ns->len; i++) { 248 if (strcmp(ns->items[i].path, path) == 0) { 249 return &ns->items[i]; 250 } 251 } 252 return NULL; 253} 254 255const tobi_ns_ent *tobi_ns_find_method(const tobi_ns *ns, const char *name) { 256 if (!ns || !name) { 257 return NULL; 258 } 259 for (size_t i = 0; i < ns->len; i++) { 260 const tobi_ns_ent *e = &ns->items[i]; 261 if (e->kind == TOBI_NS_METHOD && strcmp(e->path, name) == 0) { 262 return e; 263 } 264 } 265 for (size_t i = 0; i < ns->len; i++) { 266 const tobi_ns_ent *e = &ns->items[i]; 267 if (e->kind == TOBI_NS_METHOD && strcmp(e->name, name) == 0) { 268 return e; 269 } 270 } 271 const char *leaf = strrchr(name, '.'); 272 leaf = leaf ? leaf + 1 : name; 273 for (size_t i = 0; i < ns->len; i++) { 274 const tobi_ns_ent *e = &ns->items[i]; 275 if (e->kind == TOBI_NS_METHOD && strcmp(e->name, leaf) == 0) { 276 return e; 277 } 278 } 279 return NULL; 280} 281 282static char *ns_parent(const char *scope) { 283 if (!scope || strcmp(scope, "\\") == 0 || scope[0] == '\0') { 284 return NULL; 285 } 286 const char *dot = strrchr(scope, '.'); 287 if (!dot) { 288 return tobi_xstrdup("\\"); 289 } 290 if (dot == scope || (scope[0] == '\\' && dot == scope + 1)) { 291 return tobi_xstrdup("\\"); 292 } 293 return tobi_xstrndup(scope, (size_t)(dot - scope)); 294} 295 296static char *ns_join(const char *scope, const char *name) { 297 tobi_sb sb; 298 tobi_sb_init(&sb); 299 if (!scope || scope[0] == '\0' || strcmp(scope, "\\") == 0) { 300 tobi_sb_add(&sb, "\\"); 301 tobi_sb_add(&sb, name); 302 } else { 303 tobi_sb_add(&sb, scope); 304 tobi_sb_ch(&sb, '.'); 305 tobi_sb_add(&sb, name); 306 } 307 return tobi_sb_take(&sb); 308} 309 310static const tobi_ns_ent *ns_follow_alias(const tobi_ns *ns, const tobi_ns_ent *ent) { 311 const tobi_ns_ent *cur = ent; 312 for (unsigned i = 0; cur && cur->kind == TOBI_NS_ALIAS && cur->target && i < 16; i++) { 313 const tobi_ns_ent *next = tobi_ns_find_const(ns, cur->target); 314 if (!next || next == cur) { 315 break; 316 } 317 cur = next; 318 } 319 return cur; 320} 321 322const tobi_ns_ent *tobi_ns_lookup(const tobi_ns *ns, const char *scope, const char *name) { 323 if (!ns || !name || name[0] == '\0') { 324 return NULL; 325 } 326 if (name[0] == '\\' || name[0] == '^' || strcmp(name, "<null>") == 0) { 327 char *path = tobi_nm_resolve(scope, name); 328 const tobi_ns_ent *ent = ns_follow_alias(ns, tobi_ns_find_const(ns, path)); 329 free(path); 330 return ent; 331 } 332 char *cur = tobi_xstrdup(scope && scope[0] ? scope : "\\"); 333 for (;;) { 334 char *candidate = ns_join(cur, name); 335 const tobi_ns_ent *ent = ns_follow_alias(ns, tobi_ns_find_const(ns, candidate)); 336 free(candidate); 337 if (ent) { 338 free(cur); 339 return ent; 340 } 341 char *parent = ns_parent(cur); 342 free(cur); 343 if (!parent) { 344 break; 345 } 346 cur = parent; 347 } 348 char *root = ns_join("\\", name); 349 const tobi_ns_ent *ent = ns_follow_alias(ns, tobi_ns_find_const(ns, root)); 350 free(root); 351 return ent; 352} 353 354char *tobi_ns_resolve_path(const tobi_ns *ns, const char *scope, const char *name) { 355 const tobi_ns_ent *ent = tobi_ns_lookup(ns, scope, name); 356 if (ent) { 357 return tobi_xstrdup(ent->path); 358 } 359 return tobi_nm_resolve(scope, name); 360} 361 362tobi_ns_ent *tobi_ns_add(tobi_ns *ns, tobi_ns_kind kind, const char *path, const char *owner, 363 size_t off, unsigned args, unsigned flags, int external, 364 const char *target, int *duplicate) { 365 if (duplicate) { 366 *duplicate = 0; 367 } 368 if (!ns || !path || path[0] == '\0') { 369 return NULL; 370 } 371 tobi_ns_ent *old = tobi_ns_find(ns, path); 372 if (old) { 373 int old_is_external = old->external || old->kind == TOBI_NS_EXTERNAL; 374 int same_scope = old->kind == TOBI_NS_SCOPE && kind == TOBI_NS_SCOPE; 375 int same_decl = old->kind == kind && old->off == off; 376 if (duplicate && !same_decl && !same_scope && !(old_is_external && !external)) { 377 *duplicate = 1; 378 } 379 if (old_is_external && !external) { 380 old->kind = kind; 381 old->external = 0; 382 old->off = off; 383 old->args = args; 384 } else if (kind == TOBI_NS_METHOD && old->kind == TOBI_NS_METHOD) { 385 old->args = args; 386 } 387 old->flags = flags; 388 if (target) { 389 free(old->target); 390 old->target = tobi_xstrdup(target); 391 } 392 return old; 393 } 394 if (ns->len == ns->cap) { 395 ns->cap = ns->cap ? ns->cap * 2 : 16; 396 ns->items = tobi_xrealloc(ns->items, ns->cap * sizeof(ns->items[0])); 397 } 398 tobi_ns_ent *e = &ns->items[ns->len++]; 399 memset(e, 0, sizeof(*e)); 400 e->path = tobi_xstrdup(path); 401 e->name = tobi_xstrdup(tobi_ns_leaf(path)); 402 e->owner = tobi_xstrdup(owner && owner[0] ? owner : "\\"); 403 e->target = target ? tobi_xstrdup(target) : NULL; 404 e->kind = kind; 405 e->off = off; 406 e->args = args; 407 e->flags = flags; 408 e->external = external; 409 return e; 410}