crash.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * crash.c
  3. *
  4. * Copyright (C) 2018 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <common.h>
  20. #include <exception.h>
  21. #include <process.h>
  22. #include <module.h>
  23. #include <memory.h>
  24. #include <log.h>
  25. #include <exec/elf.h>
  26. #define MAX_BACKTRACE 256
  27. /* The background is a fabulous compromise between blue and red */
  28. #define CRASH_SCREEN_ATTRIBUTE 0x5F
  29. extern bool_t video_initialized;
  30. extern const char *lookup_kernel_symbol_name(uintptr_t address);
  31. static char screen[TEXT_WIDTH * TEXT_HEIGHT + 1] = { 0 };
  32. static const char *screen_template[TEXT_HEIGHT] = {
  33. "",
  34. " >>> KERNEL CRASH <<<",
  35. "",
  36. " A fatal error has occurred in the Monolithium kernel. The system cannot",
  37. " continue from this point in a reliable manner, and has been shut down.",
  38. " Please contact the developers so that similar issues can be prevented or",
  39. " avoided in the future.",
  40. "",
  41. " Error: %.71s",
  42. " %.78s",
  43. " In %s line %u",
  44. " Modules involved: %.60s",
  45. "",
  46. " If serial logging is enabled, more information might be available in the log.",
  47. };
  48. void __attribute__((noreturn)) kernel_crash(const char *message, registers_t *regs, const char *filename, int line)
  49. {
  50. int i;
  51. word_t *video_mem = (word_t*)(video_initialized ? VIDEO_MEMORY : TEXT_VIDEO_MEMORY);
  52. cpu_disable_interrupts();
  53. uintptr_t call_stack[MAX_BACKTRACE];
  54. int call_count = 0;
  55. uintptr_t *frame_pointer;
  56. asm volatile ("movl %%ebp, %0" : "=r"(frame_pointer) ::);
  57. while (frame_pointer && call_count < MAX_BACKTRACE)
  58. {
  59. if (!get_physical_address(&frame_pointer[1])) break;
  60. call_stack[call_count++] = frame_pointer[1];
  61. if (!get_physical_address(&frame_pointer[0])) break;
  62. frame_pointer = (uintptr_t*)frame_pointer[0];
  63. }
  64. for (i = 0; i < TEXT_HEIGHT; i++)
  65. {
  66. if (!screen_template[i]) continue;
  67. switch (i)
  68. {
  69. case 8:
  70. sprintf(&screen[i * TEXT_WIDTH], screen_template[i], message);
  71. break;
  72. case 9:
  73. if (strlen(message) > 71) sprintf(&screen[i * TEXT_WIDTH], screen_template[i], &message[71]);
  74. break;
  75. case 10:
  76. sprintf(&screen[i * TEXT_WIDTH], screen_template[i], filename, line);
  77. break;
  78. case 11:
  79. {
  80. int module_count = 0, j, k;
  81. const char *module_list[call_count];
  82. char modules[61] = "";
  83. for (j = 0; j < call_count; j++)
  84. {
  85. module_t *module = get_module_from_address((void*)call_stack[j]);
  86. if (!module) continue;
  87. bool_t found = FALSE;
  88. for (k = 0; k < module_count; k++)
  89. {
  90. if (strcmp(module_list[k], module->name) == 0)
  91. {
  92. found = TRUE;
  93. break;
  94. }
  95. }
  96. if (found) continue;
  97. module_list[module_count++] = module->name;
  98. if (module_count) strncat(modules, ", ", sizeof(modules) - strlen(modules) - 1);
  99. strncat(modules, module_list[j], sizeof(modules) - strlen(modules) - 1);
  100. }
  101. if (!strlen(modules)) sprintf(modules, "(none)");
  102. sprintf(&screen[i * TEXT_WIDTH], screen_template[i], modules);
  103. }
  104. break;
  105. default:
  106. strcpy(&screen[i * TEXT_WIDTH], screen_template[i]);
  107. }
  108. }
  109. for (i = 0; i < TEXT_WIDTH * TEXT_HEIGHT; i++) video_mem[i] = (CRASH_SCREEN_ATTRIBUTE << 8) | screen[i];
  110. log_write(LOG_CRITICAL, "******************************\n");
  111. log_write(LOG_CRITICAL, "* ATTENTION!!! *\n");
  112. log_write(LOG_CRITICAL, "******************************\n");
  113. log_write(LOG_CRITICAL, "The kernel crashed, specifying the following message:\n");
  114. log_write(LOG_CRITICAL, "%s\n", message);
  115. log_write(LOG_CRITICAL, "Crash requested in file %s line %u\n", filename, line);
  116. thread_t *thread = get_current_thread();
  117. if (thread)
  118. {
  119. log_write(LOG_CRITICAL, "Context: thread %u", thread->tid);
  120. if (thread->owner_process)
  121. {
  122. log_write(LOG_CRITICAL, ", attached to process %u (%s).\n", thread->owner_process->pid, thread->owner_process->name);
  123. }
  124. else
  125. {
  126. log_write(LOG_CRITICAL, ", not attached to any process.\n");
  127. }
  128. }
  129. else
  130. {
  131. log_write(LOG_CRITICAL, "No context available.\n");
  132. }
  133. if (regs)
  134. {
  135. const char *flag_names[32] = {
  136. "CF", NULL, "PF", NULL, "AF", NULL, "ZF", "SF",
  137. "TF", "IF", "DF", "OF", NULL, NULL, "NT", NULL,
  138. "RF", "VM", "AC", "VIF", "VIP", "ID"
  139. };
  140. log_write(LOG_CRITICAL, "Machine state:\n");
  141. log_write(LOG_CRITICAL, "EAX: 0x%08X\n", regs->eax);
  142. log_write(LOG_CRITICAL, "ECX: 0x%08X\n", regs->ecx);
  143. log_write(LOG_CRITICAL, "EDX: 0x%08X\n", regs->edx);
  144. log_write(LOG_CRITICAL, "EBX: 0x%08X\n", regs->ebx);
  145. log_write(LOG_CRITICAL, "ESP: 0x%08X\n", regs->esp);
  146. log_write(LOG_CRITICAL, "EBP: 0x%08X\n", regs->ebp);
  147. log_write(LOG_CRITICAL, "ESI: 0x%08X\n", regs->eax);
  148. log_write(LOG_CRITICAL, "EDI: 0x%08X\n", regs->eax);
  149. log_write(LOG_CRITICAL, "EIP: 0x%08X\n", regs->eip);
  150. log_write(LOG_CRITICAL, "Code: 0x%04X\n", regs->cs);
  151. log_write(LOG_CRITICAL, "Data: 0x%04X\n", regs->data_selector);
  152. log_write(LOG_CRITICAL, "EFLAGS: %08X ( ", regs->eflags);
  153. for (i = 0; i < 32; i++)
  154. {
  155. if (flag_names[i] && regs->eflags & (1 << i))
  156. {
  157. log_write(LOG_CRITICAL, "%s ", flag_names[i]);
  158. }
  159. }
  160. log_write(LOG_CRITICAL, ")\n");
  161. log_write(LOG_CRITICAL, "CR0: 0x%08X\n", cpu_read_master_control_register());
  162. log_write(LOG_CRITICAL, "CR2: 0x%08X\n", cpu_read_faulting_address());
  163. log_write(LOG_CRITICAL, "CR3: 0x%08X\n", cpu_read_page_table_register());
  164. log_write(LOG_CRITICAL, "CR4: 0x%08X\n", cpu_read_feature_register());
  165. }
  166. else
  167. {
  168. log_write(LOG_CRITICAL, "No machine state available.\n");
  169. }
  170. log_write(LOG_CRITICAL, "Backtrace:\n");
  171. for (i = 0; i < call_count; i++)
  172. {
  173. log_write(LOG_CRITICAL, "0x%08X", call_stack[i]);
  174. module_t *module = get_module_from_address((void*)call_stack[i]);
  175. extern int _end;
  176. if (module)
  177. {
  178. log_write(LOG_CRITICAL, " in module %s", module->name);
  179. }
  180. else if (call_stack[i] >= KERNEL_AREA_START && call_stack[i] < (uintptr_t)&_end)
  181. {
  182. log_write(LOG_CRITICAL, " in the kernel");
  183. const char *function_name = lookup_kernel_symbol_name(call_stack[i]);
  184. if (function_name) log_write(LOG_CRITICAL, ", function %s", function_name);
  185. }
  186. log_write(LOG_CRITICAL, "\n");
  187. }
  188. cpu_halt();
  189. for(;;);
  190. }