Kernel+ProfileViewer: Move symbolication to userspace for time profiles

This makes the time profiles look like the memory profiles so we can
use the userspace symbolication code in ProfileViewer.
This commit is contained in:
Andreas Kling 2020-02-22 10:05:03 +01:00
parent 94652fd2fb
commit 983b4bd9f2
Notes: sideshowbarker 2024-07-19 09:10:43 +09:00
5 changed files with 32 additions and 62 deletions

View File

@ -44,13 +44,7 @@ int main(int argc, char** argv)
}
const char* path = argv[1];
OwnPtr<Profile> profile;
if (!strcmp(path, "perfcore")) {
profile = Profile::load_from_perfcore_file(path);
} else {
profile = Profile::load_from_file(path);
}
auto profile = Profile::load_from_perfcore_file(path);
if (!profile) {
fprintf(stderr, "Unable to load profile '%s'\n", path);

View File

@ -398,29 +398,31 @@ Optional<KBuffer> procfs$profile(InodeIdentifier)
{
InterruptDisabler disabler;
KBufferBuilder builder;
JsonArraySerializer array(builder);
JsonObjectSerializer object(builder);
object.add("pid", Profiling::pid());
object.add("executable", Profiling::executable_path());
auto array = object.add_array("events");
bool mask_kernel_addresses = !Process::current->is_superuser();
Profiling::for_each_sample([&](auto& sample) {
auto object = array.add_object();
object.add("pid", sample.pid);
object.add("type", "sample");
object.add("tid", sample.tid);
object.add("timestamp", sample.timestamp);
auto frames_array = object.add_array("frames");
auto frames_array = object.add_array("stack");
for (size_t i = 0; i < Profiling::max_stack_frame_count; ++i) {
if (sample.frames[i] == 0)
break;
auto frame_object = frames_array.add_object();
u32 address = (u32)sample.frames[i];
if (mask_kernel_addresses && !is_user_address(VirtualAddress(address)))
address = 0xdeadc0de;
frame_object.add("address", address);
frame_object.add("symbol", sample.symbolicated_frames[i]);
frame_object.add("offset", JsonValue((u32)sample.offsets[i]));
frame_object.finish();
frames_array.add(address);
}
frames_array.finish();
});
array.finish();
object.finish();
return builder.build();
}

View File

@ -26,6 +26,7 @@
#include <AK/JsonArraySerializer.h>
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonObject.h>
#include <Kernel/KBufferBuilder.h>
#include <Kernel/PerformanceEventBuffer.h>

View File

@ -41,11 +41,28 @@ static KBufferImpl* s_profiling_buffer;
static size_t s_slot_count;
static size_t s_next_slot_index;
static Process* s_process;
static u32 s_pid;
String& executable_path()
{
static String* path;
if (!path)
path = new String;
return *path;
}
u32 pid()
{
return s_pid;
}
void start(Process& process)
{
s_process = &process;
executable_path() = process.executable()->absolute_path().impl();
s_pid = process.pid();
if (!s_profiling_buffer) {
s_profiling_buffer = RefPtr<KBufferImpl>(KBuffer::create_with_size(8 * MB).impl()).leak_ref();
s_profiling_buffer->region().commit();
@ -68,53 +85,8 @@ Sample& next_sample_slot()
return slot;
}
static void symbolicate(Sample& stack)
{
auto& process = *s_process;
ProcessPagingScope paging_scope(process);
struct RecognizedSymbol {
u32 address;
const KSym* ksym;
};
Vector<RecognizedSymbol, max_stack_frame_count> recognized_symbols;
for (size_t i = 1; i < max_stack_frame_count; ++i) {
if (stack.frames[i] == 0)
break;
recognized_symbols.append({ stack.frames[i], ksymbolicate(stack.frames[i]) });
}
size_t i = 1;
for (auto& symbol : recognized_symbols) {
if (!symbol.address)
break;
auto& symbol_string_slot = stack.symbolicated_frames[i];
auto& offset_slot = stack.offsets[i];
++i;
if (!symbol.ksym) {
if (!Scheduler::is_active() && process.elf_loader() && process.elf_loader()->has_symbols())
symbol_string_slot = process.elf_loader()->symbolicate(symbol.address, &offset_slot);
else
symbol_string_slot = String::empty();
continue;
}
u32 offset = symbol.address - symbol.ksym->address;
if (symbol.ksym->address == ksym_highest_address && offset > 4096) {
symbol_string_slot = String::empty();
offset_slot = 0;
} else {
symbol_string_slot = demangle(symbol.ksym->name);
offset_slot = offset;
}
}
}
void stop()
{
for (size_t i = 0; i < s_next_slot_index; ++i) {
auto& stack = sample_slot(i);
symbolicate(stack);
}
s_process = nullptr;
}

View File

@ -43,10 +43,11 @@ struct Sample {
i32 tid;
u64 timestamp;
u32 frames[max_stack_frame_count];
u32 offsets[max_stack_frame_count];
String symbolicated_frames[max_stack_frame_count];
};
extern u32 pid();
extern String& executable_path();
Sample& next_sample_slot();
void start(Process&);
void stop();