This repository has been archived on 2023-11-05. You can view files and clone it, but cannot push or open issues or pull requests.
wasm-micro-runtime/core/iwasm/aot/debug/jit_debug.c
Wenyong Huang 52b6c73d9c
Apply clang-format for more src files and update spec test script (#775)
Apply clang-format for core/iwasm/include, core/iwasm/common and
core/iwasm/aot files.

Update spec cases test script:
- Checkout latest commit of https://github.com/WebAssembly/spec
- Checkout main branch but not master of https://github.com/WebAssembly/threads
- Update wabt to latest version

And update source debugging document.

Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
2021-10-08 17:47:11 +08:00

256 lines
6.8 KiB
C

/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (C) 2021 Ant Group. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "bh_log.h"
#include "bh_platform.h"
#include "../../interpreter/wasm_runtime.h"
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
/* This must be kept in sync with gdb/gdb/jit.h */
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
typedef enum JITAction {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} JITAction;
/* clang-format on */
typedef struct JITCodeEntry {
struct JITCodeEntry *next_;
struct JITCodeEntry *prev_;
const uint8 *symfile_addr_;
uint64 symfile_size_;
} JITCodeEntry;
typedef struct JITDescriptor {
uint32 version_;
uint32 action_flag_;
JITCodeEntry *relevant_entry_;
JITCodeEntry *first_entry_;
} JITDescriptor;
/* LLVM has already define this */
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0)
/**
* GDB will place breakpoint into this function.
* To prevent GCC from inlining or removing it we place noinline attribute
* and inline assembler statement inside.
*/
void __attribute__((noinline)) __jit_debug_register_code();
void __attribute__((noinline)) __jit_debug_register_code()
{
int x;
*(char *)&x = '\0';
}
/**
* GDB will inspect contents of this descriptor.
* Static initialization is necessary to prevent GDB from seeing
* uninitialized descriptor.
*/
JITDescriptor __jit_debug_descriptor = { 1, JIT_NOACTION, NULL, NULL };
#else
extern void
__jit_debug_register_code();
extern JITDescriptor __jit_debug_descriptor;
#endif
/**
* Call __jit_debug_register_code indirectly via global variable.
* This gives the debugger an easy way to inject custom code to
* handle the events.
*/
void (*__jit_debug_register_code_ptr)() = __jit_debug_register_code;
#ifdef __cplusplus
}
#endif
typedef struct WASMJITDebugEngine {
korp_mutex jit_entry_lock;
bh_list jit_entry_list;
} WASMJITDebugEngine;
typedef struct WASMJITEntryNode {
struct WASMJITEntryNode *next;
JITCodeEntry *entry;
} WASMJITEntryNode;
static WASMJITDebugEngine *jit_debug_engine;
static JITCodeEntry *
CreateJITCodeEntryInternal(const uint8 *symfile_addr, uint64 symfile_size)
{
JITCodeEntry *entry;
os_mutex_lock(&jit_debug_engine->jit_entry_lock);
if (!(entry = wasm_runtime_malloc(sizeof(JITCodeEntry)))) {
LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
return NULL;
}
entry->symfile_addr_ = symfile_addr;
entry->symfile_size_ = symfile_size;
entry->prev_ = NULL;
entry->next_ = __jit_debug_descriptor.first_entry_;
if (entry->next_ != NULL) {
entry->next_->prev_ = entry;
}
__jit_debug_descriptor.first_entry_ = entry;
__jit_debug_descriptor.relevant_entry_ = entry;
__jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
(*__jit_debug_register_code_ptr)();
os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
return entry;
}
static void
DestroyJITCodeEntryInternal(JITCodeEntry *entry)
{
os_mutex_lock(&jit_debug_engine->jit_entry_lock);
if (entry->prev_ != NULL) {
entry->prev_->next_ = entry->next_;
}
else {
__jit_debug_descriptor.first_entry_ = entry->next_;
}
if (entry->next_ != NULL) {
entry->next_->prev_ = entry->prev_;
}
__jit_debug_descriptor.relevant_entry_ = entry;
__jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
(*__jit_debug_register_code_ptr)();
wasm_runtime_free(entry);
os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
}
bool
jit_debug_engine_init()
{
if (jit_debug_engine) {
return true;
}
if (!(jit_debug_engine = wasm_runtime_malloc(sizeof(WASMJITDebugEngine)))) {
LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
return false;
}
memset(jit_debug_engine, 0, sizeof(WASMJITDebugEngine));
if (os_mutex_init(&jit_debug_engine->jit_entry_lock) != 0) {
wasm_runtime_free(jit_debug_engine);
jit_debug_engine = NULL;
return false;
}
bh_list_init(&jit_debug_engine->jit_entry_list);
return true;
}
void
jit_debug_engine_destroy()
{
if (jit_debug_engine) {
WASMJITEntryNode *node, *node_next;
/* Destroy all nodes */
node = bh_list_first_elem(&jit_debug_engine->jit_entry_list);
while (node) {
node_next = bh_list_elem_next(node);
DestroyJITCodeEntryInternal(node->entry);
bh_list_remove(&jit_debug_engine->jit_entry_list, node);
wasm_runtime_free(node);
node = node_next;
}
/* Destroy JIT Debug Engine */
os_mutex_destroy(&jit_debug_engine->jit_entry_lock);
wasm_runtime_free(jit_debug_engine);
jit_debug_engine = NULL;
}
}
bool
jit_code_entry_create(const uint8 *symfile_addr, uint64 symfile_size)
{
JITCodeEntry *entry;
WASMJITEntryNode *node;
if (!(node = wasm_runtime_malloc(sizeof(WASMJITEntryNode)))) {
LOG_ERROR("WASM JIT Debug Engine error: failed to allocate memory");
return false;
}
entry = CreateJITCodeEntryInternal(symfile_addr, symfile_size);
if (!entry) {
wasm_runtime_free(node);
return false;
}
node->entry = entry;
os_mutex_lock(&jit_debug_engine->jit_entry_lock);
bh_list_insert(&jit_debug_engine->jit_entry_list, node);
os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
return true;
}
void
jit_code_entry_destroy(const uint8 *symfile_addr)
{
WASMJITEntryNode *node;
node = bh_list_first_elem(&jit_debug_engine->jit_entry_list);
while (node) {
WASMJITEntryNode *next_node = bh_list_elem_next(node);
if (node->entry->symfile_addr_ == symfile_addr) {
DestroyJITCodeEntryInternal(node->entry);
os_mutex_lock(&jit_debug_engine->jit_entry_lock);
bh_list_remove(&jit_debug_engine->jit_entry_list, node);
os_mutex_unlock(&jit_debug_engine->jit_entry_lock);
wasm_runtime_free(node);
}
node = next_node;
}
}