| 1 | #include "internal.h" |
| 2 | |
| 3 | #include <console/printf.h> |
| 4 | #include <math/hash.h> |
| 5 | #include <nightmare/record.h> |
| 6 | #include <stdarg.h> |
| 7 | |
| 8 | #ifdef TEST_NIGHTMARE_ENABLED |
| 9 | static uint64_t fnv1a_string(uint64_t hash, const char *str) { |
| 10 | const char *value = str ? str : "" ; |
| 11 | return hash_fnv1a_64_update(hash, key: value, len: strlen(str: value)); |
| 12 | } |
| 13 | |
| 14 | void nightmare_finding_at(const struct nightmare_finding_site *site, |
| 15 | uint64_t discriminator, const char *fmt, ...) { |
| 16 | char msg[256]; |
| 17 | va_list args; |
| 18 | va_start(args, fmt); |
| 19 | vsnprintf(buffer: msg, buffer_len: (int) sizeof(msg), format: fmt, args); |
| 20 | va_end(args); |
| 21 | |
| 22 | uint64_t signature = HASH_FNV1A_64_OFFSET_BASIS; |
| 23 | signature = fnv1a_string(hash: signature, str: nightmare_runtime.ctx.nm |
| 24 | ? nightmare_runtime.ctx.nm->name |
| 25 | : "unknown" ); |
| 26 | signature = fnv1a_string(hash: signature, str: site->kind); |
| 27 | signature = fnv1a_string(hash: signature, str: site->file); |
| 28 | signature = |
| 29 | hash_fnv1a_64_update(hash: signature, key: &site->line, len: sizeof(site->line)); |
| 30 | signature = |
| 31 | hash_fnv1a_64_update(hash: signature, key: &discriminator, len: sizeof(discriminator)); |
| 32 | |
| 33 | char sig[24]; |
| 34 | char location[192]; |
| 35 | snprintf(buffer: sig, buffer_len: (int) sizeof(sig), format: "%016lx" , signature); |
| 36 | snprintf(buffer: location, buffer_len: (int) sizeof(location), format: "%s:%u" , site->file, site->line); |
| 37 | |
| 38 | nightmare_record_finding(record: &(struct nightmare_finding_record){ |
| 39 | .kind = site->kind, |
| 40 | .tier = |
| 41 | site->tier == NIGHTMARE_TIER_CONFIDENT ? "confident" : "ambiguous" , |
| 42 | .sig = sig, |
| 43 | .site = location, |
| 44 | .msg = msg, |
| 45 | }); |
| 46 | atomic_fetch_add_explicit(&nightmare_runtime.finding_count, 1, |
| 47 | memory_order_relaxed); |
| 48 | } |
| 49 | |
| 50 | void nightmare_request_external_fail(const char *kind, uint64_t discriminator, |
| 51 | const char *fmt, ...) { |
| 52 | if (!atomic_load_explicit(&nightmare_runtime.active, memory_order_acquire)) |
| 53 | return; |
| 54 | |
| 55 | char msg[256]; |
| 56 | va_list args; |
| 57 | va_start(args, fmt); |
| 58 | vsnprintf(buffer: msg, buffer_len: (int) sizeof(msg), format: fmt, args); |
| 59 | va_end(args); |
| 60 | |
| 61 | nightmare_finding_at( |
| 62 | site: &(const struct nightmare_finding_site){ |
| 63 | .kind = kind, |
| 64 | .tier = NIGHTMARE_TIER_CONFIDENT, |
| 65 | .file = __RELFILE__, |
| 66 | .line = __LINE__, |
| 67 | }, |
| 68 | discriminator, fmt: "%s" , msg); |
| 69 | |
| 70 | nightmare_publish_stop(reason: NM_STOP_FAIL); |
| 71 | } |
| 72 | #else |
| 73 | void nightmare_request_external_fail(const char *kind, uint64_t discriminator, |
| 74 | const char *fmt, ...) { |
| 75 | unused(kind, discriminator, fmt); |
| 76 | } |
| 77 | #endif |
| 78 | |