|
|
@@ -2764,6 +2764,104 @@ fail:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#if WASM_ENABLE_LINUX_PERF != 0
|
|
|
+struct func_info {
|
|
|
+ uint32 idx;
|
|
|
+ void *ptr;
|
|
|
+};
|
|
|
+
|
|
|
+static uint32
|
|
|
+get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
|
|
|
+ uint32 idx)
|
|
|
+{
|
|
|
+ uint32 func_sz;
|
|
|
+
|
|
|
+ if (idx == module->func_count - 1)
|
|
|
+ func_sz = (uintptr_t)module->code + module->code_size
|
|
|
+ - (uintptr_t)(sorted_func_ptrs[idx].ptr);
|
|
|
+ else
|
|
|
+ func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
|
|
|
+ - (uintptr_t)(sorted_func_ptrs[idx].ptr);
|
|
|
+
|
|
|
+ return func_sz;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+compare_func_ptrs(const void *f1, const void *f2)
|
|
|
+{
|
|
|
+ return (intptr_t)((struct func_info *)f1)->ptr
|
|
|
+ - (intptr_t)((struct func_info *)f2)->ptr;
|
|
|
+}
|
|
|
+
|
|
|
+static struct func_info *
|
|
|
+sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
|
|
|
+{
|
|
|
+ uint64 content_len;
|
|
|
+ struct func_info *sorted_func_ptrs;
|
|
|
+ unsigned i;
|
|
|
+
|
|
|
+ content_len = (uint64)sizeof(struct func_info) * module->func_count;
|
|
|
+ sorted_func_ptrs = loader_malloc(content_len, error_buf, error_buf_size);
|
|
|
+ if (!sorted_func_ptrs)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ for (i = 0; i < module->func_count; i++) {
|
|
|
+ sorted_func_ptrs[i].idx = i;
|
|
|
+ sorted_func_ptrs[i].ptr = module->func_ptrs[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
|
|
|
+ compare_func_ptrs);
|
|
|
+
|
|
|
+ return sorted_func_ptrs;
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+create_perf_map(const AOTModule *module, char *error_buf, uint32 error_buf_size)
|
|
|
+{
|
|
|
+ struct func_info *sorted_func_ptrs = NULL;
|
|
|
+ char perf_map_info[128] = { 0 };
|
|
|
+ FILE *perf_map = NULL;
|
|
|
+ uint32 i;
|
|
|
+ pid_t pid = getpid();
|
|
|
+ bool ret = false;
|
|
|
+
|
|
|
+ sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
|
|
|
+ if (!sorted_func_ptrs)
|
|
|
+ goto quit;
|
|
|
+
|
|
|
+ snprintf(perf_map_info, 128, "/tmp/perf-%d.map", pid);
|
|
|
+ perf_map = fopen(perf_map_info, "w");
|
|
|
+ if (!perf_map) {
|
|
|
+ LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
|
|
|
+ strerror(errno));
|
|
|
+ goto quit;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < module->func_count; i++) {
|
|
|
+ memset(perf_map_info, 0, 128);
|
|
|
+ snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
|
|
|
+ (uintptr_t)sorted_func_ptrs[i].ptr,
|
|
|
+ get_func_size(module, sorted_func_ptrs, i),
|
|
|
+ sorted_func_ptrs[i].idx);
|
|
|
+
|
|
|
+ fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
|
|
|
+ }
|
|
|
+
|
|
|
+ LOG_VERBOSE("generate /tmp/perf-%d.map", pid);
|
|
|
+ ret = true;
|
|
|
+
|
|
|
+quit:
|
|
|
+ if (sorted_func_ptrs)
|
|
|
+ free(sorted_func_ptrs);
|
|
|
+
|
|
|
+ if (perf_map)
|
|
|
+ fclose(perf_map);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif /* WASM_ENABLE_LINUX_PERF != 0*/
|
|
|
+
|
|
|
static bool
|
|
|
load_from_sections(AOTModule *module, AOTSection *sections,
|
|
|
bool is_load_from_file_buf, char *error_buf,
|
|
|
@@ -3224,6 +3322,12 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#if WASM_ENABLE_LINUX_PERF != 0
|
|
|
+ if (wasm_runtime_get_linux_perf())
|
|
|
+ if (!create_perf_map(module, error_buf, error_buf_size))
|
|
|
+ goto fail;
|
|
|
+#endif
|
|
|
+
|
|
|
return ret;
|
|
|
fail:
|
|
|
return false;
|