// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later /* * Misc utility functions * * Copyright 2013-2018 IBM Corp. */ #include #include #include #include #include #include #include void __noreturn assert_fail(const char *msg, const char *file, unsigned int line, const char *function) { static bool in_abort = false; (void)function; if (in_abort) for (;;) ; in_abort = true; /** * @fwts-label FailedAssert2 * @fwts-advice OPAL hit an assert(). During normal usage (even * testing) we should never hit an assert. There are other code * paths for controlled shutdown/panic in the event of catastrophic * errors. */ prlog(PR_EMERG, "assert failed at %s:%u: %s\n", file, line, msg); backtrace(); if (platform.terminate) platform.terminate(msg); for (;;) ; } char __attrconst tohex(uint8_t nibble) { static const char __tohex[] = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; if (nibble > 0xf) return '?'; return __tohex[nibble]; } static unsigned long get_symbol(unsigned long addr, char **sym, char **sym_end) { unsigned long prev = 0, next; char *psym = NULL, *p = __sym_map_start; *sym = *sym_end = NULL; while(p < __sym_map_end) { next = strtoul(p, &p, 16) | SKIBOOT_BASE; if (next > addr && prev <= addr) { p = psym + 3;; if (p >= __sym_map_end) return 0; *sym = p; while(p < __sym_map_end && *p != 10) p++; *sym_end = p; return prev; } prev = next; psym = p; while(p < __sym_map_end && *p != 10) p++; p++; } return 0; } size_t snprintf_symbol(char *buf, size_t len, uint64_t addr) { unsigned long saddr; char *sym, *sym_end; size_t l; saddr = get_symbol(addr, &sym, &sym_end); if (!saddr) return 0; if (len > sym_end - sym) l = sym_end - sym; else l = len - 1; memcpy(buf, sym, l); /* * This snprintf will insert the terminating NUL even if the * symbol has used up the entire buffer less 1. */ l += snprintf(buf + l, len - l, "+0x%llx", addr - saddr); return l; }