Profiling.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include <AK/Demangle.h>
  2. #include <AK/StringBuilder.h>
  3. #include <Kernel/FileSystem/Custody.h>
  4. #include <Kernel/KBuffer.h>
  5. #include <Kernel/Process.h>
  6. #include <Kernel/Profiling.h>
  7. #include <LibELF/ELFLoader.h>
  8. namespace Profiling {
  9. static KBufferImpl* s_profiling_buffer;
  10. static size_t s_slot_count;
  11. static size_t s_next_slot_index;
  12. static Process* s_process;
  13. void start(Process& process)
  14. {
  15. s_process = &process;
  16. if (!s_profiling_buffer) {
  17. s_profiling_buffer = RefPtr<KBufferImpl>(KBuffer::create_with_size(8 * MB).impl()).leak_ref();
  18. s_slot_count = s_profiling_buffer->size() / sizeof(Sample);
  19. }
  20. s_next_slot_index = 0;
  21. }
  22. static Sample& sample_slot(size_t index)
  23. {
  24. return ((Sample*)s_profiling_buffer->data())[index];
  25. }
  26. Sample& next_sample_slot()
  27. {
  28. auto& slot = sample_slot(s_next_slot_index++);
  29. if (s_next_slot_index >= s_slot_count)
  30. s_next_slot_index = 0;
  31. return slot;
  32. }
  33. static void symbolicate(Sample& stack)
  34. {
  35. auto& process = *s_process;
  36. ProcessPagingScope paging_scope(process);
  37. struct RecognizedSymbol {
  38. u32 address;
  39. const KSym* ksym;
  40. };
  41. Vector<RecognizedSymbol, max_stack_frame_count> recognized_symbols;
  42. for (size_t i = 1; i < max_stack_frame_count; ++i) {
  43. if (stack.frames[i] == 0)
  44. break;
  45. recognized_symbols.append({ stack.frames[i], ksymbolicate(stack.frames[i]) });
  46. }
  47. size_t i = 1;
  48. for (auto& symbol : recognized_symbols) {
  49. if (!symbol.address)
  50. break;
  51. auto& symbol_string_slot = stack.symbolicated_frames[i++];
  52. if (!symbol.ksym) {
  53. if (!Scheduler::is_active() && process.elf_loader() && process.elf_loader()->has_symbols())
  54. symbol_string_slot = String::format("%s", process.elf_loader()->symbolicate(symbol.address).characters());
  55. else
  56. symbol_string_slot = String::empty();
  57. continue;
  58. }
  59. unsigned offset = symbol.address - symbol.ksym->address;
  60. if (symbol.ksym->address == ksym_highest_address && offset > 4096)
  61. symbol_string_slot = String::empty();
  62. else
  63. symbol_string_slot = String::format("%s +%u", demangle(symbol.ksym->name).characters(), offset);
  64. }
  65. }
  66. void stop()
  67. {
  68. for (size_t i = 0; i < s_next_slot_index; ++i) {
  69. auto& stack = sample_slot(i);
  70. symbolicate(stack);
  71. }
  72. s_process = nullptr;
  73. }
  74. void for_each_sample(Function<void(Sample&)> callback)
  75. {
  76. for (size_t i = 0; i < s_next_slot_index; ++i) {
  77. auto& sample = sample_slot(i);
  78. callback(sample);
  79. }
  80. }
  81. }