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
9static 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
14void 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
50void 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
73void nightmare_request_external_fail(const char *kind, uint64_t discriminator,
74 const char *fmt, ...) {
75 unused(kind, discriminator, fmt);
76}
77#endif
78