Implement source debugging for interpreter and AOT (#769)
Implement source debugging feature for classic interpreter and AOT: - use `cmake -DWAMR_BUILD_DEBUG_INTERP=1` to enable interpreter debugging - use `cmake -DWAMR_BUILD_DEBUG_AOT=1` to enable AOT debugging See doc/source_debugging.md for more details.
This commit is contained in:
@ -21,6 +21,10 @@ typedef InitializerExpression AOTInitExpr;
|
||||
typedef WASMType AOTFuncType;
|
||||
typedef WASMExport AOTExport;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
typedef void * dwar_extractor_handle_t;
|
||||
#endif
|
||||
|
||||
typedef enum AOTIntCond {
|
||||
INT_EQZ = 0,
|
||||
INT_EQ,
|
||||
@ -251,6 +255,9 @@ typedef struct AOTCompData {
|
||||
uint32 aux_stack_size;
|
||||
|
||||
WASMModule *wasm_module;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
dwar_extractor_handle_t extractor;
|
||||
#endif
|
||||
} AOTCompData;
|
||||
|
||||
typedef struct AOTNativeSymbol {
|
||||
|
||||
@ -32,6 +32,9 @@
|
||||
#include "../interpreter/wasm_opcode.h"
|
||||
#include <errno.h>
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "debug/dwarf_extractor.h"
|
||||
#endif
|
||||
|
||||
#define CHECK_BUF(buf, buf_end, length) do { \
|
||||
if (buf + length > buf_end) { \
|
||||
@ -153,6 +156,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
||||
float32 f32_const;
|
||||
float64 f64_const;
|
||||
AOTFuncType *func_type = NULL;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef location;
|
||||
#endif
|
||||
|
||||
/* Start to translate the opcodes */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder,
|
||||
@ -160,6 +166,15 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
||||
->llvm_entry_block);
|
||||
while (frame_ip < frame_ip_end) {
|
||||
opcode = *frame_ip++;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
location = dwarf_gen_location(
|
||||
comp_ctx, func_ctx,
|
||||
(frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code
|
||||
);
|
||||
LLVMSetCurrentDebugLocation2(comp_ctx->builder, location);
|
||||
#endif
|
||||
|
||||
switch (opcode) {
|
||||
case WASM_OP_UNREACHABLE:
|
||||
if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip))
|
||||
@ -2440,6 +2455,10 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||
errno = 0;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMDIBuilderFinalize(comp_ctx->debug_builder);
|
||||
#endif
|
||||
|
||||
bh_print_time("Begin to verify LLVM module");
|
||||
|
||||
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
|
||||
|
||||
@ -1757,22 +1757,34 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
|
||||
static bool
|
||||
aot_resolve_text(AOTObjectData *obj_data)
|
||||
{
|
||||
LLVMSectionIteratorRef sec_itr;
|
||||
char *name;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary);
|
||||
if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF64L) {
|
||||
obj_data->text = (char *)LLVMGetBufferStart(obj_data->mem_buf);
|
||||
obj_data->text_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LLVMSectionIteratorRef sec_itr;
|
||||
char *name;
|
||||
|
||||
if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get section iterator failed.");
|
||||
return false;
|
||||
}
|
||||
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".text")) {
|
||||
obj_data->text = (char *)LLVMGetSectionContents(sec_itr);
|
||||
obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr);
|
||||
break;
|
||||
if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
|
||||
aot_set_last_error("llvm get section iterator failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMMoveToNextSection(sec_itr);
|
||||
while (
|
||||
!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
|
||||
if ((name = (char *)LLVMGetSectionName(sec_itr))
|
||||
&& !strcmp(name, ".text")) {
|
||||
obj_data->text = (char *)LLVMGetSectionContents(sec_itr);
|
||||
obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr);
|
||||
break;
|
||||
}
|
||||
LLVMMoveToNextSection(sec_itr);
|
||||
}
|
||||
LLVMDisposeSectionIterator(sec_itr);
|
||||
}
|
||||
LLVMDisposeSectionIterator(sec_itr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8,6 +8,10 @@
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "../interpreter/wasm_loader.h"
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "debug/dwarf_extractor.h"
|
||||
#endif
|
||||
|
||||
static char *block_name_prefix[] = { "block", "loop", "if" };
|
||||
static char *block_name_suffix[] = { "begin", "else", "end" };
|
||||
|
||||
@ -158,14 +162,22 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
|
||||
uint8 *frame_ip = NULL;
|
||||
uint32 i;
|
||||
AOTFuncType *func_type;
|
||||
LLVMValueRef ret;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef return_location;
|
||||
#endif
|
||||
|
||||
aot_checked_addr_list_destroy(func_ctx);
|
||||
|
||||
bh_assert(block);
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
return_location = dwarf_gen_location(
|
||||
comp_ctx, func_ctx,
|
||||
(*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code
|
||||
);
|
||||
#endif
|
||||
if (block->label_type == LABEL_TYPE_IF
|
||||
&& block->llvm_else_block
|
||||
&& !block->skip_wasm_code_else
|
||||
&& *p_frame_ip <= block->wasm_code_else) {
|
||||
/* Clear value stack and start to translate else branch */
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
@ -237,16 +249,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
|
||||
if (block->label_type == LABEL_TYPE_FUNCTION) {
|
||||
if (block->result_count) {
|
||||
/* Return the first return value */
|
||||
if (!LLVMBuildRet(comp_ctx->builder, block->result_phis[0])) {
|
||||
if (!(ret =
|
||||
LLVMBuildRet(comp_ctx->builder, block->result_phis[0]))) {
|
||||
aot_set_last_error("llvm build return failed.");
|
||||
goto fail;
|
||||
}
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMInstructionSetDebugLoc(ret, return_location);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (!LLVMBuildRetVoid(comp_ctx->builder)) {
|
||||
if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
|
||||
aot_set_last_error("llvm build return void failed.");
|
||||
goto fail;
|
||||
}
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMInstructionSetDebugLoc(ret, return_location);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
aot_block_destroy(block);
|
||||
@ -381,7 +400,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
memset(block_addr_cache, 0, sizeof(block_addr_cache));
|
||||
|
||||
/* Get block info */
|
||||
if (!(wasm_loader_find_block_addr((BlockAddr*)block_addr_cache,
|
||||
if (!(wasm_loader_find_block_addr(NULL, (BlockAddr*)block_addr_cache,
|
||||
*p_frame_ip, frame_ip_end, (uint8)label_type,
|
||||
&else_addr, &end_addr))) {
|
||||
aot_set_last_error("find block end addr failed.");
|
||||
@ -709,7 +728,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
|
||||
/* Move builder to terminate block */
|
||||
SET_BUILDER_POS(terminate_block);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1070,12 +1089,22 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
{
|
||||
AOTBlock *block_func = func_ctx->block_stack.block_list_head;
|
||||
LLVMValueRef value;
|
||||
LLVMValueRef ret;
|
||||
AOTFuncType *func_type;
|
||||
uint32 i, param_index, result_index;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef return_location;
|
||||
#endif
|
||||
|
||||
bh_assert(block_func);
|
||||
func_type = func_ctx->aot_func->func_type;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
return_location = dwarf_gen_location(
|
||||
comp_ctx, func_ctx,
|
||||
(*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code
|
||||
);
|
||||
#endif
|
||||
if (block_func->result_count) {
|
||||
/* Store extra result values to function parameters */
|
||||
for (i = 0; i < block_func->result_count - 1; i++) {
|
||||
@ -1091,16 +1120,22 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
}
|
||||
/* Return the first result value */
|
||||
POP(value, block_func->result_types[0]);
|
||||
if (!LLVMBuildRet(comp_ctx->builder, value)) {
|
||||
if (!(ret = LLVMBuildRet(comp_ctx->builder, value))) {
|
||||
aot_set_last_error("llvm build return failed.");
|
||||
goto fail;
|
||||
}
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMInstructionSetDebugLoc(ret, return_location);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (!LLVMBuildRetVoid(comp_ctx->builder)) {
|
||||
if (!(ret = LLVMBuildRetVoid(comp_ctx->builder))) {
|
||||
aot_set_last_error("llvm build return void failed.");
|
||||
goto fail;
|
||||
}
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMInstructionSetDebugLoc(ret, return_location);
|
||||
#endif
|
||||
}
|
||||
|
||||
return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
|
||||
|
||||
@ -109,7 +109,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
||||
/* Create return IR */
|
||||
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
|
||||
/* Create return IR */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -313,7 +313,7 @@ call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
/* If frame alloc failed, return this function
|
||||
so the runtime can catch the exception */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, frame_alloc_fail);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -897,7 +897,7 @@ aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
/* If memory.init failed, return this function
|
||||
so the runtime can catch the exception */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, mem_init_fail);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1231,7 +1231,7 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
/* If atomic wait failed, return this function
|
||||
so the runtime can catch the exception */
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_fail);
|
||||
if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
|
||||
if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,10 @@
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "../aot/aot_intrinsic.h"
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "debug/dwarf_extractor.h"
|
||||
#endif
|
||||
|
||||
LLVMTypeRef
|
||||
wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
|
||||
{
|
||||
@ -634,6 +638,10 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
func, aot_func_type)))
|
||||
goto fail;
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
func_ctx->debug_func = dwarf_gen_func_info(comp_ctx, func_ctx);
|
||||
#endif
|
||||
|
||||
aot_block_stack_push(&func_ctx->block_stack, aot_block);
|
||||
|
||||
/* Add local variables */
|
||||
@ -1462,6 +1470,29 @@ aot_create_comp_context(AOTCompData *comp_data,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) {
|
||||
aot_set_last_error("create LLVM Debug Infor builder failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMAddModuleFlag(
|
||||
comp_ctx->module, LLVMModuleFlagBehaviorWarning, "Debug Info Version",
|
||||
strlen("Debug Info Version"),
|
||||
LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 3, false)));
|
||||
|
||||
comp_ctx->debug_file = dwarf_gen_file_info(comp_ctx);
|
||||
if (!comp_ctx->debug_file) {
|
||||
aot_set_last_error("dwarf generate file info failed");
|
||||
goto fail;
|
||||
}
|
||||
comp_ctx->debug_comp_unit = dwarf_gen_comp_unit_info(comp_ctx);
|
||||
if (!comp_ctx->debug_comp_unit) {
|
||||
aot_set_last_error("dwarf generate compile unit info failed");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (option->enable_bulk_memory)
|
||||
comp_ctx->enable_bulk_memory = true;
|
||||
|
||||
@ -2213,6 +2244,7 @@ aot_checked_addr_list_destroy(AOTFuncContext *func_ctx)
|
||||
|
||||
bool
|
||||
aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
AOTFuncType *func_type)
|
||||
{
|
||||
LLVMValueRef ret = NULL;
|
||||
@ -2251,6 +2283,10 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
aot_set_last_error("llvm build ret failed.");
|
||||
return false;
|
||||
}
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef return_location = dwarf_gen_func_ret_location(comp_ctx, func_ctx);
|
||||
LLVMInstructionSetDebugLoc(ret, return_location);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
#include "llvm-c/Initialization.h"
|
||||
#include "llvm-c/Support.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "llvm-c/DebugInfo.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -148,6 +151,9 @@ typedef struct AOTFuncContext {
|
||||
LLVMBasicBlockRef func_return_block;
|
||||
LLVMValueRef exception_id_phi;
|
||||
LLVMValueRef func_type_indexes;
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
LLVMMetadataRef debug_func;
|
||||
#endif
|
||||
LLVMValueRef locals[1];
|
||||
} AOTFuncContext;
|
||||
|
||||
@ -245,6 +251,11 @@ typedef struct AOTCompContext {
|
||||
LLVMContextRef context;
|
||||
LLVMModuleRef module;
|
||||
LLVMBuilderRef builder;
|
||||
#if WASM_ENABLE_DEBUG_AOT
|
||||
LLVMDIBuilderRef debug_builder;
|
||||
LLVMMetadataRef debug_file;
|
||||
LLVMMetadataRef debug_comp_unit;
|
||||
#endif
|
||||
LLVMTargetMachineRef target_machine;
|
||||
char *target_cpu;
|
||||
char target_arch[16];
|
||||
@ -407,6 +418,7 @@ aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_build_zero_function_ret(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
AOTFuncType *func_type);
|
||||
|
||||
LLVMValueRef
|
||||
|
||||
530
core/iwasm/compilation/debug/dwarf_extractor.cpp
Normal file
530
core/iwasm/compilation/debug/dwarf_extractor.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Ant Group. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "lldb/API/SBBlock.h"
|
||||
#include "lldb/API/SBCompileUnit.h"
|
||||
#include "lldb/API/SBCommandReturnObject.h"
|
||||
#include "lldb/API/SBCommandInterpreter.h"
|
||||
#include "lldb/API/SBBreakpointLocation.h"
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
#include "lldb/API//SBFunction.h"
|
||||
#include "lldb/API//SBModule.h"
|
||||
#include "lldb/API//SBProcess.h"
|
||||
#include "lldb/API//SBStream.h"
|
||||
#include "lldb/API//SBSymbol.h"
|
||||
#include "lldb/API//SBTarget.h"
|
||||
#include "lldb/API//SBThread.h"
|
||||
#include "lldb/API/SBDeclaration.h"
|
||||
|
||||
#include "dwarf_extractor.h"
|
||||
#include "../aot_llvm.h"
|
||||
|
||||
#include "bh_log.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
|
||||
using namespace lldb;
|
||||
|
||||
typedef struct dwar_extractor
|
||||
{
|
||||
SBDebugger debugger;
|
||||
SBTarget target;
|
||||
SBModule module;
|
||||
|
||||
} dwar_extractor;
|
||||
|
||||
#define TO_HANDLE(extractor) (dwar_extractor_handle_t)(extractor)
|
||||
|
||||
#define TO_EXTACTOR(handle) (dwar_extractor *)(handle)
|
||||
|
||||
static bool is_debugger_initialized;
|
||||
|
||||
dwar_extractor_handle_t
|
||||
create_dwarf_extractor(AOTCompData *comp_data, char * file_name)
|
||||
{
|
||||
char *arch = NULL;
|
||||
char *platform = NULL;
|
||||
dwar_extractor * extractor = NULL;
|
||||
|
||||
//__attribute__((constructor)) may be better?
|
||||
if (!is_debugger_initialized) {
|
||||
SBError error = SBDebugger::InitializeWithErrorHandling();
|
||||
if(error.Fail()) {
|
||||
LOG_ERROR("Init Dwarf Debugger failed");
|
||||
return TO_HANDLE(NULL);
|
||||
}
|
||||
is_debugger_initialized = true;
|
||||
}
|
||||
|
||||
SBError error;
|
||||
SBFileSpec exe_file_spec(file_name, true);
|
||||
|
||||
if (!(extractor = new dwar_extractor()) ) {
|
||||
LOG_ERROR("Create Dwarf Extractor error: failed to allocate memory");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
extractor->debugger = SBDebugger::Create();
|
||||
if (!extractor->debugger.IsValid()) {
|
||||
LOG_ERROR("Create Dwarf Debugger failed");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
extractor->target = extractor->debugger.CreateTarget(
|
||||
file_name, arch, platform, false, error);
|
||||
|
||||
if (!error.Success()) {
|
||||
LOG_ERROR("Create Dwarf target failed:%s", error.GetCString());
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (!extractor->target.IsValid()) {
|
||||
LOG_ERROR("Create Dwarf target not valid");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
extractor->module = extractor->target.FindModule(exe_file_spec);
|
||||
comp_data->extractor = TO_HANDLE(extractor);
|
||||
|
||||
return TO_HANDLE(extractor);
|
||||
|
||||
fail1:
|
||||
SBDebugger::Destroy(extractor->debugger);
|
||||
|
||||
fail2:
|
||||
wasm_runtime_free(extractor);
|
||||
|
||||
fail3:
|
||||
return TO_HANDLE(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
destroy_dwarf_extractor(dwar_extractor_handle_t handle)
|
||||
{
|
||||
dwar_extractor * extractor = TO_EXTACTOR(handle);
|
||||
if (!extractor)
|
||||
return;
|
||||
extractor->debugger.DeleteTarget(extractor->target);
|
||||
SBDebugger::Destroy(extractor->debugger);
|
||||
delete extractor;
|
||||
SBDebugger::Terminate();
|
||||
is_debugger_initialized = false;
|
||||
}
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_file_info(AOTCompContext *comp_ctx)
|
||||
{
|
||||
dwar_extractor *extractor;
|
||||
int units_number;
|
||||
LLVMMetadataRef file_info = NULL;
|
||||
const char *file_name;
|
||||
const char *dir_name;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
units_number = extractor->module.GetNumCompileUnits();
|
||||
|
||||
if (units_number > 0) {
|
||||
SBCompileUnit compile_unit =
|
||||
extractor->module.GetCompileUnitAtIndex(0);
|
||||
auto filespec = compile_unit.GetFileSpec();
|
||||
file_name = filespec.GetFilename();
|
||||
dir_name = filespec.GetDirectory();
|
||||
if (file_name || dir_name) {
|
||||
file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder,
|
||||
file_name, strlen(file_name),
|
||||
dir_name, strlen(dir_name));
|
||||
}
|
||||
}
|
||||
return file_info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
dwarf_gen_mock_vm_info(AOTCompContext *comp_ctx)
|
||||
{
|
||||
LLVMMetadataRef file_info = NULL;
|
||||
LLVMMetadataRef comp_unit = NULL;
|
||||
file_info = LLVMDIBuilderCreateFile(comp_ctx->debug_builder,
|
||||
"ant_runtime_mock.c", 18, ".", 1);
|
||||
|
||||
comp_unit = LLVMDIBuilderCreateCompileUnit(
|
||||
comp_ctx->debug_builder, LLVMDWARFSourceLanguageC, file_info,
|
||||
"ant compiler", 12, 0, NULL, 0, 1, NULL, 0, LLVMDWARFEmissionFull, 0, 0,
|
||||
0, "/", 1, "", 0);
|
||||
|
||||
LLVMTypeRef ParamTys[] = {
|
||||
LLVMVoidType(),
|
||||
};
|
||||
|
||||
LLVMTypeRef FuncTy = LLVMFunctionType(LLVMVoidType(), ParamTys, 0, 0);
|
||||
|
||||
LLVMValueRef Function =
|
||||
LLVMAddFunction(comp_ctx->module, "ant_runtime_mock", FuncTy);
|
||||
|
||||
LLVMMetadataRef ParamTypes[0];
|
||||
LLVMMetadataRef FunctionTy = LLVMDIBuilderCreateSubroutineType(
|
||||
comp_ctx->debug_builder, file_info, ParamTypes, 0, LLVMDIFlagZero);
|
||||
|
||||
/* 0x0015 is subroutine_type */
|
||||
LLVMMetadataRef ReplaceableFunctionMetadata =
|
||||
LLVMDIBuilderCreateReplaceableCompositeType(
|
||||
comp_ctx->debug_builder, 0x15, "ant_runtime_mock", 16, file_info,
|
||||
file_info, 2, 0, 0, 0, LLVMDIFlagFwdDecl, "", 0);
|
||||
|
||||
LLVMMetadataRef FunctionMetadata = LLVMDIBuilderCreateFunction(
|
||||
comp_ctx->debug_builder, file_info, "ant_runtime_mock", 16,
|
||||
"ant_runtime_mock", 16, file_info, 2, FunctionTy, true, true, 2, LLVMDIFlagZero,
|
||||
false);
|
||||
|
||||
LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata,
|
||||
FunctionMetadata);
|
||||
|
||||
LLVMSetSubprogram(Function, FunctionMetadata);
|
||||
|
||||
comp_ctx->vm_debug_comp_unit = comp_unit;
|
||||
comp_ctx->vm_debug_file = file_info;
|
||||
comp_ctx->vm_debug_func = FunctionMetadata;
|
||||
}
|
||||
#endif
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx)
|
||||
{
|
||||
dwar_extractor *extractor;
|
||||
int units_number;
|
||||
LLVMMetadataRef comp_unit = NULL;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
units_number = extractor->module.GetNumCompileUnits();
|
||||
|
||||
if (units_number > 0) {
|
||||
SBCompileUnit compile_unit =
|
||||
extractor->module.GetCompileUnitAtIndex(0);
|
||||
auto lang_type = compile_unit.GetLanguage();
|
||||
|
||||
comp_unit = LLVMDIBuilderCreateCompileUnit(
|
||||
comp_ctx->debug_builder, LLDB_TO_LLVM_LANG_TYPE(lang_type),
|
||||
comp_ctx->debug_file, "ant compiler", 12, 0, NULL, 0, 1, NULL, 0,
|
||||
LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0);
|
||||
}
|
||||
return comp_unit;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
dwarf_get_func_info(dwar_extractor_handle_t handle, uint64_t offset)
|
||||
{
|
||||
dwar_extractor *extractor = TO_EXTACTOR(handle);
|
||||
auto sbaddr = extractor->target.ResolveFileAddress(offset);
|
||||
SBSymbolContext sc(
|
||||
sbaddr.GetSymbolContext(eSymbolContextFunction));
|
||||
if (sc.IsValid()) {
|
||||
SBFunction function(sc.GetFunction());
|
||||
if (function.IsValid()) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMDWARFTypeEncoding
|
||||
lldb_get_basic_type_encoding(BasicType basic_type)
|
||||
{
|
||||
LLVMDWARFTypeEncoding encoding = 0;
|
||||
switch (basic_type)
|
||||
{
|
||||
case eBasicTypeUnsignedChar:
|
||||
encoding = llvm::dwarf::DW_ATE_unsigned_char;
|
||||
break;
|
||||
case eBasicTypeSignedChar:
|
||||
encoding = llvm::dwarf::DW_ATE_signed_char;
|
||||
break;
|
||||
case eBasicTypeUnsignedInt:
|
||||
case eBasicTypeUnsignedLong:
|
||||
case eBasicTypeUnsignedLongLong:
|
||||
case eBasicTypeUnsignedWChar:
|
||||
case eBasicTypeUnsignedInt128:
|
||||
case eBasicTypeUnsignedShort:
|
||||
encoding = llvm::dwarf::DW_ATE_unsigned;
|
||||
break;
|
||||
case eBasicTypeInt:
|
||||
case eBasicTypeLong:
|
||||
case eBasicTypeLongLong:
|
||||
case eBasicTypeWChar:
|
||||
case eBasicTypeInt128:
|
||||
case eBasicTypeShort:
|
||||
encoding = llvm::dwarf::DW_ATE_signed;
|
||||
break;
|
||||
case eBasicTypeBool:
|
||||
encoding = llvm::dwarf::DW_ATE_boolean;
|
||||
break;
|
||||
case eBasicTypeHalf:
|
||||
case eBasicTypeFloat:
|
||||
case eBasicTypeDouble:
|
||||
case eBasicTypeLongDouble:
|
||||
encoding = llvm::dwarf::DW_ATE_float;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return encoding;
|
||||
}
|
||||
|
||||
static LLVMMetadataRef
|
||||
lldb_type_to_type_dbi(AOTCompContext *comp_ctx, SBType &type)
|
||||
{
|
||||
LLVMMetadataRef type_info = NULL;
|
||||
BasicType basic_type = type.GetBasicType();
|
||||
uint64_t bit_size = type.GetByteSize() * 8;
|
||||
LLVMDIBuilderRef DIB = comp_ctx->debug_builder;
|
||||
LLVMDWARFTypeEncoding encoding;
|
||||
|
||||
if (basic_type != eBasicTypeInvalid) {
|
||||
encoding = lldb_get_basic_type_encoding(basic_type);
|
||||
type_info = LLVMDIBuilderCreateBasicType(
|
||||
DIB, type.GetName(), strlen(type.GetName()), bit_size, encoding,
|
||||
LLVMDIFlagZero);
|
||||
}
|
||||
else if (type.IsPointerType()) {
|
||||
SBType pointee_type = type.GetPointeeType();
|
||||
type_info = LLVMDIBuilderCreatePointerType(
|
||||
DIB, lldb_type_to_type_dbi(comp_ctx, pointee_type), bit_size, 0, 0,
|
||||
"", 0);
|
||||
}
|
||||
|
||||
return type_info;
|
||||
}
|
||||
|
||||
static LLVMMetadataRef
|
||||
lldb_function_to_function_dbi(AOTCompContext *comp_ctx, SBSymbolContext &sc, AOTFuncContext *func_ctx)
|
||||
{
|
||||
SBFunction function(sc.GetFunction());
|
||||
const char *function_name = function.GetName();
|
||||
const char *link_name = function.GetName();
|
||||
SBTypeList function_args = function.GetType().GetFunctionArgumentTypes();
|
||||
SBType return_type = function.GetType().GetFunctionReturnType();
|
||||
const size_t num_function_args = function_args.GetSize();
|
||||
dwar_extractor *extractor;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
|
||||
LLVMDIBuilderRef DIB = comp_ctx->debug_builder;
|
||||
LLVMMetadataRef File = comp_ctx->debug_file;
|
||||
|
||||
LLVMMetadataRef ParamTypes[num_function_args + 1];
|
||||
|
||||
|
||||
ParamTypes[0] = lldb_type_to_type_dbi(comp_ctx, return_type);
|
||||
|
||||
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args;
|
||||
++function_arg_idx) {
|
||||
SBType function_arg_type =
|
||||
function_args.GetTypeAtIndex(function_arg_idx);
|
||||
|
||||
if (function_arg_type.IsValid()) {
|
||||
ParamTypes[function_arg_idx + 1] = lldb_type_to_type_dbi(comp_ctx, function_arg_type);
|
||||
}
|
||||
}
|
||||
|
||||
LLVMMetadataRef FunctionTy =
|
||||
LLVMDIBuilderCreateSubroutineType(DIB, File, ParamTypes, num_function_args + 1, LLVMDIFlagZero);
|
||||
|
||||
auto line_entry = sc.GetLineEntry();
|
||||
LLVMMetadataRef ReplaceableFunctionMetadata =
|
||||
LLVMDIBuilderCreateReplaceableCompositeType(
|
||||
DIB, 0x15, function_name, strlen(function_name), File, File,
|
||||
line_entry.GetLine(), 0, 0, 0, LLVMDIFlagFwdDecl, "", 0);
|
||||
|
||||
LLVMMetadataRef FunctionMetadata =
|
||||
LLVMDIBuilderCreateFunction(DIB, File, function_name, strlen(function_name), link_name, strlen(link_name),
|
||||
File, line_entry.GetLine(), FunctionTy, true, true, line_entry.GetLine(), LLVMDIFlagZero, false);
|
||||
|
||||
LLVMMetadataReplaceAllUsesWith(ReplaceableFunctionMetadata, FunctionMetadata);
|
||||
|
||||
LLVMSetSubprogram(func_ctx->func, FunctionMetadata);
|
||||
|
||||
LLVMMetadataRef ParamExpression = LLVMDIBuilderCreateExpression(DIB, NULL, 0);
|
||||
auto variable_list = function.GetBlock().GetVariables(extractor->target, true, false,false);
|
||||
if (num_function_args != variable_list.GetSize())
|
||||
{
|
||||
LOG_ERROR("function args number dismatch!:value number=%d, function args=%d", variable_list.GetSize(), num_function_args);
|
||||
}
|
||||
|
||||
LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
|
||||
comp_ctx->context, line_entry.GetLine(), 0, FunctionMetadata, NULL);
|
||||
|
||||
//TODO:change to void * or WasmExenv * ?
|
||||
LLVMMetadataRef voidtype = LLVMDIBuilderCreateBasicType(DIB, "void", 4, 0, 0, LLVMDIFlagZero);
|
||||
LLVMMetadataRef voidpionter = LLVMDIBuilderCreatePointerType(DIB, voidtype, 64, 0, 0, "void *", 6);
|
||||
|
||||
LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable(
|
||||
DIB, FunctionMetadata, "exenv",
|
||||
5, 1,
|
||||
File, //starts form 1, and 1 is exenv,
|
||||
line_entry.GetLine(), voidpionter, true,
|
||||
LLVMDIFlagZero);
|
||||
LLVMValueRef Param =
|
||||
LLVMGetParam(func_ctx->func, 0);
|
||||
LLVMBasicBlockRef block_curr =
|
||||
LLVMGetEntryBasicBlock(func_ctx->func);
|
||||
LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar,
|
||||
ParamExpression, ParamLocation,
|
||||
block_curr);
|
||||
|
||||
for (uint32_t function_arg_idx = 0; function_arg_idx < variable_list.GetSize();
|
||||
++function_arg_idx) {
|
||||
SBValue variable(variable_list.GetValueAtIndex(function_arg_idx));
|
||||
if (variable.IsValid()) {
|
||||
SBDeclaration dec(variable.GetDeclaration());
|
||||
auto valtype = variable.GetType();
|
||||
LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
|
||||
comp_ctx->context, dec.GetLine(), dec.GetColumn(),
|
||||
FunctionMetadata, NULL);
|
||||
LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable(
|
||||
DIB, FunctionMetadata, variable.GetName(),
|
||||
strlen(variable.GetName()), function_arg_idx + 1 + 1,
|
||||
File, //starts form 1, and 1 is exenv,
|
||||
dec.GetLine(), ParamTypes[function_arg_idx + 1], true,
|
||||
LLVMDIFlagZero);
|
||||
LLVMValueRef Param =
|
||||
LLVMGetParam(func_ctx->func, function_arg_idx + 1);
|
||||
LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar,
|
||||
ParamExpression, ParamLocation,
|
||||
block_curr);
|
||||
}
|
||||
}
|
||||
|
||||
return FunctionMetadata;
|
||||
}
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
// A code address in DWARF for WebAssembly is the offset of an
|
||||
// instruction relative within the Code section of the WebAssembly file.
|
||||
// For this reason Section::GetFileAddress() must return zero for the
|
||||
// Code section. (refert to ObjectFileWasm.cpp)
|
||||
vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code;
|
||||
|
||||
auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
|
||||
SBSymbolContext sc(
|
||||
sbaddr.GetSymbolContext(eSymbolContextFunction | eSymbolContextLineEntry));
|
||||
if (sc.IsValid()) {
|
||||
SBFunction function(sc.GetFunction());
|
||||
if (function.IsValid()) {
|
||||
func_info = lldb_function_to_function_dbi(comp_ctx, sc, func_ctx);
|
||||
}
|
||||
}
|
||||
return func_info;
|
||||
}
|
||||
|
||||
void
|
||||
dwarf_get_func_name(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
char *name,
|
||||
int len)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
name[0] = '\0';
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return ;
|
||||
|
||||
// A code address in DWARF for WebAssembly is the offset of an
|
||||
// instruction relative within the Code section of the WebAssembly file.
|
||||
// For this reason Section::GetFileAddress() must return zero for the
|
||||
// Code section. (refert to ObjectFileWasm.cpp)
|
||||
vm_offset = func->code - comp_ctx->comp_data->wasm_module->buf_code;
|
||||
|
||||
auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
|
||||
SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction
|
||||
| eSymbolContextLineEntry));
|
||||
if (sc.IsValid()) {
|
||||
SBFunction function(sc.GetFunction());
|
||||
if (function.IsValid()) {
|
||||
bh_strcpy_s(name, len, function.GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_location(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint64_t vm_offset)
|
||||
{
|
||||
LLVMMetadataRef location_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
auto sbaddr = extractor->target.ResolveFileAddress(vm_offset);
|
||||
SBSymbolContext sc(sbaddr.GetSymbolContext(eSymbolContextFunction
|
||||
| eSymbolContextLineEntry));
|
||||
if (sc.IsValid()) {
|
||||
//TODO:need to check if the vm_offset is belong to
|
||||
SBFunction function(sc.GetFunction());
|
||||
if (function.IsValid()) {
|
||||
uint64_t start = func_ctx->aot_func->code
|
||||
- comp_ctx->comp_data->wasm_module->buf_code;
|
||||
uint64_t end = func_ctx->aot_func->code
|
||||
- comp_ctx->comp_data->wasm_module->buf_code
|
||||
+ func_ctx->aot_func->code_size;
|
||||
if (function.GetStartAddress().GetOffset() <= start
|
||||
&& end <= function.GetEndAddress().GetOffset()) {
|
||||
auto line_entry = sc.GetLineEntry();
|
||||
location_info =
|
||||
LLVMDIBuilderCreateDebugLocation(
|
||||
comp_ctx->context, line_entry.GetLine(),
|
||||
line_entry.GetColumn(), func_ctx->debug_func, NULL);
|
||||
//LOG_VERBOSE("Gen the location l:%d, c:%d at %lx", line_entry.GetLine(), line_entry.GetColumn(), vm_offset);
|
||||
} else
|
||||
LOG_WARNING("the offset and function is not matched");
|
||||
}
|
||||
}
|
||||
return location_info;
|
||||
}
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_func_ret_location(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMMetadataRef func_info = NULL;
|
||||
dwar_extractor *extractor;
|
||||
uint64_t vm_offset;
|
||||
AOTFunc *func = func_ctx->aot_func;
|
||||
LLVMMetadataRef location_info = NULL;
|
||||
|
||||
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
|
||||
return NULL;
|
||||
|
||||
// A code address in DWARF for WebAssembly is the offset of an
|
||||
// instruction relative within the Code section of the WebAssembly file.
|
||||
// For this reason Section::GetFileAddress() must return zero for the
|
||||
// Code section. (refert to ObjectFileWasm.cpp)
|
||||
vm_offset = (func->code + func->code_size -1) - comp_ctx->comp_data->wasm_module->buf_code;
|
||||
location_info = dwarf_gen_location(comp_ctx, func_ctx, vm_offset);
|
||||
|
||||
return location_info;
|
||||
}
|
||||
58
core/iwasm/compilation/debug/dwarf_extractor.h
Normal file
58
core/iwasm/compilation/debug/dwarf_extractor.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Ant Group. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _DWARF_EXTRACTOR_H_
|
||||
#define _DWARF_EXTRACTOR_H_
|
||||
|
||||
#include "llvm-c/DebugInfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef unsigned int LLDBLangType;
|
||||
#define LLDB_TO_LLVM_LANG_TYPE(lldb_lang_type) \
|
||||
(LLVMDWARFSourceLanguage)(((lldb_lang_type) > 0 ? (lldb_lang_type)-1 : 1))
|
||||
|
||||
struct AOTCompData;
|
||||
typedef struct AOTCompData *aot_comp_data_t;
|
||||
typedef void *dwar_extractor_handle_t;
|
||||
|
||||
struct AOTCompContext;
|
||||
typedef struct AOTCompContext AOTCompContext;
|
||||
|
||||
struct AOTFuncContext;
|
||||
|
||||
typedef struct AOTFuncContext AOTFuncContext;
|
||||
dwar_extractor_handle_t
|
||||
create_dwarf_extractor(aot_comp_data_t comp_data, char *file_name);
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_file_info(AOTCompContext *comp_ctx);
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_comp_unit_info(AOTCompContext *comp_ctx);
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_func_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_location(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint64_t vm_offset);
|
||||
|
||||
LLVMMetadataRef
|
||||
dwarf_gen_func_ret_location(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
void
|
||||
dwarf_get_func_name(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
char *name,
|
||||
int len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -2,9 +2,17 @@ set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${IWASM_COMPL_DIR})
|
||||
|
||||
file (GLOB_RECURSE source_all
|
||||
${IWASM_COMPL_DIR}/*.c
|
||||
${IWASM_COMPL_DIR}/*.cpp)
|
||||
if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
|
||||
file (GLOB_RECURSE source_all
|
||||
${IWASM_COMPL_DIR}/*.c
|
||||
${IWASM_COMPL_DIR}/*.cpp)
|
||||
else()
|
||||
file (GLOB source_all
|
||||
${IWASM_COMPL_DIR}/simd/*.c
|
||||
${IWASM_COMPL_DIR}/simd/*.cpp
|
||||
${IWASM_COMPL_DIR}/*.c
|
||||
${IWASM_COMPL_DIR}/*.cpp)
|
||||
endif()
|
||||
|
||||
set (IWASM_COMPL_SOURCE ${source_all})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user