Move everything under kotlin-native folder
I was forced to manually do update the following files, because otherwise they would be ignored according .gitignore settings. Probably they should be deleted from repo. Interop/.idea/compiler.xml Interop/.idea/gradle.xml Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_3.xml Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_3.xml Interop/.idea/modules.xml Interop/.idea/modules/Indexer/Indexer.iml Interop/.idea/modules/Runtime/Runtime.iml Interop/.idea/modules/StubGenerator/StubGenerator.iml backend.native/backend.native.iml backend.native/bc.frontend/bc.frontend.iml backend.native/cli.bc/cli.bc.iml backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt backend.native/tests/link/lib/foo.kt backend.native/tests/link/lib/foo2.kt backend.native/tests/teamcity-test.property
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
/**
|
||||
* This code was generated with following command:
|
||||
* $ clang -xc -E -Idist/dependencies/clang-llvm-3.9.0-darwin-macos/include/ llvmDebugInfoC/src/dwarf/include/dwarf_util.kt.pp -Wp,-P -Wp,-CC -o - | sed -e '/^$/d' -e '/^\ *\/\/.*$/d' > backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Dwarf.kt
|
||||
*
|
||||
*/
|
||||
|
||||
internal enum class DwarfTag(val value:Int) {
|
||||
#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME(ID),
|
||||
#include "llvm/Support/Dwarf.def"
|
||||
#undef HANDLE_DW_TAG
|
||||
}
|
||||
|
||||
internal enum class DwarfTypeKind(val value:Byte) {
|
||||
#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME(ID),
|
||||
#include "llvm/Support/Dwarf.def"
|
||||
#undef HANDLE_DW_ATE
|
||||
}
|
||||
|
||||
internal enum class DwarfOp(val value:Long) {
|
||||
#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME(ID),
|
||||
#include "llvm/Support/Dwarf.def"
|
||||
#undef HANDLE_DW_OP
|
||||
}
|
||||
|
||||
internal enum class DwarfLanguage(val value:Int) {
|
||||
#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME(ID),
|
||||
#include "llvm/Support/Dwarf.def"
|
||||
#undef HANDLE_DW_LANG
|
||||
DW_LANG_Kotlin(0x0001) /* manually added, should be changed someday. */
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <llvm/IR/DebugInfo.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/DIBuilder.h>
|
||||
#include <llvm/IR/DebugInfoMetadata.h>
|
||||
#include <llvm/IR/Instruction.h>
|
||||
#include <llvm/Support/Casting.h>
|
||||
#include <llvm-c/DebugInfo.h>
|
||||
#include "DebugInfoC.h"
|
||||
/**
|
||||
* c++ --std=c++14 llvmDebugInfoC/src/DebugInfoC.cpp -IllvmDebugInfoC/include/ -Idependencies/all/clang+llvm-3.9.0-darwin-macos/include -Ldependencies/all/clang+llvm-3.9.0-darwin-macos/lib -lLLVMCore -lLLVMSupport -lncurses -shared -o libLLVMDebugInfoC.dylib
|
||||
*/
|
||||
|
||||
namespace llvm {
|
||||
//DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, DIBuilderRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DICompileUnit, DICompileUnitRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIFile, DIFileRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBasicType, DIBasicTypeRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DICompositeType, DICompositeTypeRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIType, DITypeOpaqueRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIDerivedType, DIDerivedTypeRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIModule, DIModuleRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIScope, DIScopeOpaqueRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DISubroutineType, DISubroutineTypeRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DISubprogram, DISubprogramRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DILocation, DILocationRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DILocalVariable, DILocalVariableRef)
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIExpression, DIExpressionRef)
|
||||
|
||||
// from Module.cpp
|
||||
//DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef)
|
||||
}
|
||||
|
||||
/**
|
||||
* see [DIFlags::FlagFwdDecl].
|
||||
*/
|
||||
#define DI_FORWARD_DECLARAION (4)
|
||||
extern "C" {
|
||||
|
||||
void DIFinalize(DIBuilderRef builder) {
|
||||
auto diBuilder = llvm::unwrap(builder);
|
||||
diBuilder->finalize();
|
||||
}
|
||||
|
||||
DICompileUnitRef DICreateCompilationUnit(DIBuilderRef builder, unsigned int lang,
|
||||
const char *file, const char* dir,
|
||||
const char * producer, int isOptimized,
|
||||
const char * flags, unsigned int rv) {
|
||||
llvm::DIBuilder *D = llvm::unwrap(builder);
|
||||
return llvm::wrap(llvm::unwrap(builder)->createCompileUnit(lang, D->createFile(file, dir), producer, isOptimized, flags, rv));
|
||||
}
|
||||
|
||||
DIFileRef DICreateFile(DIBuilderRef builder, const char *filename, const char *directory) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createFile(filename, directory));
|
||||
}
|
||||
|
||||
DIBasicTypeRef DICreateBasicType(DIBuilderRef builder, const char* name, uint64_t sizeInBits, uint64_t alignment, unsigned encoding) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createBasicType(name, sizeInBits, encoding));
|
||||
}
|
||||
|
||||
DIModuleRef DICreateModule(DIBuilderRef builder, DIScopeOpaqueRef scope,
|
||||
const char* name, const char* configurationMacro,
|
||||
const char* includePath, const char *iSysRoot) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createModule(llvm::unwrap(scope), name, configurationMacro, includePath, iSysRoot));
|
||||
}
|
||||
|
||||
DISubprogramRef DICreateFunction(DIBuilderRef builderRef, DIScopeOpaqueRef scope,
|
||||
const char* name, const char *linkageName,
|
||||
DIFileRef file, unsigned lineNo,
|
||||
DISubroutineTypeRef type, int isLocal,
|
||||
int isDefinition, unsigned scopeLine) {
|
||||
auto builder = llvm::unwrap(builderRef);
|
||||
auto subprogram = builder->createFunction(llvm::unwrap(scope),
|
||||
name,
|
||||
linkageName,
|
||||
llvm::unwrap(file),
|
||||
lineNo,
|
||||
llvm::unwrap(type),
|
||||
scopeLine, llvm::DINode::DIFlags::FlagZero, llvm::DISubprogram::toSPFlags(false, true, false));
|
||||
auto tmp = subprogram->getRetainedNodes().get();
|
||||
if (!tmp && tmp->isTemporary())
|
||||
llvm::MDTuple::deleteTemporary(tmp);
|
||||
|
||||
builder->finalizeSubprogram(subprogram);
|
||||
return llvm::wrap(subprogram);
|
||||
}
|
||||
|
||||
DIScopeOpaqueRef DICreateLexicalBlockFile(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef) {
|
||||
return llvm::wrap(llvm::unwrap(builderRef)->createLexicalBlockFile(llvm::unwrap(scopeRef), llvm::unwrap(fileRef)));
|
||||
}
|
||||
|
||||
DIScopeOpaqueRef DICreateLexicalBlock(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef, int line, int column) {
|
||||
return llvm::wrap(llvm::unwrap(builderRef)->createLexicalBlock(llvm::unwrap(scopeRef), llvm::unwrap(fileRef), line, column));
|
||||
}
|
||||
|
||||
|
||||
DICompositeTypeRef DICreateStructType(DIBuilderRef refBuilder,
|
||||
DIScopeOpaqueRef scope, const char *name,
|
||||
DIFileRef file, unsigned lineNumber,
|
||||
uint64_t sizeInBits, uint64_t alignInBits,
|
||||
unsigned flags, DITypeOpaqueRef derivedFrom,
|
||||
DIDerivedTypeRef *elements,
|
||||
uint64_t elementsCount,
|
||||
DICompositeTypeRef refPlace) {
|
||||
auto builder = llvm::unwrap(refBuilder);
|
||||
if ((flags & DI_FORWARD_DECLARAION) != 0) {
|
||||
auto tmp = builder->createReplaceableCompositeType(
|
||||
llvm::dwarf::DW_TAG_structure_type, name, llvm::unwrap(scope), llvm::unwrap(file), lineNumber, 0, sizeInBits, alignInBits,
|
||||
(llvm::DINode::DIFlags)flags);
|
||||
builder->replaceTemporary(llvm::TempDIType(tmp), tmp);
|
||||
builder->retainType(tmp);
|
||||
return llvm::wrap(tmp);
|
||||
}
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder,
|
||||
uint64_t size, uint64_t alignInBits,
|
||||
DITypeOpaqueRef refType,
|
||||
uint64_t elementsCount) {
|
||||
auto builder = llvm::unwrap(refBuilder);
|
||||
auto range = std::vector<llvm::Metadata*>({llvm::dyn_cast<llvm::Metadata>(builder->getOrCreateSubrange(0, size))});
|
||||
auto type = builder->createArrayType(size, alignInBits, llvm::unwrap(refType),
|
||||
builder->getOrCreateArray(range));
|
||||
builder->retainType(type);
|
||||
return llvm::wrap(type);
|
||||
}
|
||||
|
||||
|
||||
DIDerivedTypeRef DICreateMemberType(DIBuilderRef refBuilder,
|
||||
DIScopeOpaqueRef refScope,
|
||||
const char *name,
|
||||
DIFileRef file,
|
||||
unsigned lineNum,
|
||||
uint64_t sizeInBits,
|
||||
uint64_t alignInBits,
|
||||
uint64_t offsetInBits,
|
||||
unsigned flags,
|
||||
DITypeOpaqueRef type) {
|
||||
return llvm::wrap(llvm::unwrap(refBuilder)->createMemberType(
|
||||
llvm::unwrap(refScope),
|
||||
name,
|
||||
llvm::unwrap(file),
|
||||
lineNum,
|
||||
sizeInBits,
|
||||
alignInBits,
|
||||
offsetInBits,
|
||||
(llvm::DINode::DIFlags)flags,
|
||||
llvm::unwrap(type)));
|
||||
}
|
||||
|
||||
DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder,
|
||||
int tag,
|
||||
const char *name,
|
||||
DIScopeOpaqueRef refScope,
|
||||
DIFileRef refFile,
|
||||
unsigned line) {
|
||||
auto builder = llvm::unwrap(refBuilder);
|
||||
auto type = builder->createReplaceableCompositeType(
|
||||
tag, name, llvm::unwrap(refScope), llvm::unwrap(refFile), line);
|
||||
builder->retainType(type);
|
||||
return llvm::wrap(type);
|
||||
}
|
||||
|
||||
DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType) {
|
||||
auto builder = llvm::unwrap(refBuilder);
|
||||
auto type = builder->createReferenceType(
|
||||
llvm::dwarf::DW_TAG_reference_type,
|
||||
llvm::unwrap(refType));
|
||||
builder->retainType(type);
|
||||
return llvm::wrap(type);
|
||||
}
|
||||
|
||||
DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType) {
|
||||
auto builder = llvm::unwrap(refBuilder);
|
||||
auto type = builder->createReferenceType(
|
||||
llvm::dwarf::DW_TAG_pointer_type,
|
||||
llvm::unwrap(refType));
|
||||
builder->retainType(type);
|
||||
return llvm::wrap(type);
|
||||
}
|
||||
|
||||
DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder,
|
||||
DITypeOpaqueRef* types,
|
||||
unsigned typesCount) {
|
||||
std::vector<llvm::Metadata *> parameterTypes;
|
||||
for (int i = 0; i != typesCount; ++i) {
|
||||
parameterTypes.push_back(llvm::unwrap(types[i]));
|
||||
}
|
||||
llvm::DIBuilder *b = llvm::unwrap(builder);
|
||||
llvm::DITypeRefArray typeArray = b->getOrCreateTypeArray(parameterTypes);
|
||||
auto type = b->createSubroutineType(typeArray);
|
||||
b->retainType(type);
|
||||
return llvm::wrap(type);
|
||||
}
|
||||
|
||||
void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp) {
|
||||
auto f = llvm::cast<llvm::Function>(llvm::unwrap(fn));
|
||||
auto dsp = llvm::cast<llvm::DISubprogram>(llvm::unwrap(sp));
|
||||
f->setSubprogram(dsp);
|
||||
if (!dsp->describes(f)) {
|
||||
fprintf(stderr, "error!!! f:%s, sp:%s\n", f->getName().str().c_str(), dsp->getLinkageName().str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createAutoVariable(
|
||||
llvm::unwrap(scope),
|
||||
name,
|
||||
llvm::unwrap(file),
|
||||
line,
|
||||
llvm::unwrap(type)));
|
||||
}
|
||||
|
||||
DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createParameterVariable(
|
||||
llvm::unwrap(scope),
|
||||
name,
|
||||
argNo,
|
||||
llvm::unwrap(file),
|
||||
line,
|
||||
llvm::unwrap(type)));
|
||||
}
|
||||
|
||||
DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->createExpression());
|
||||
}
|
||||
|
||||
void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount) {
|
||||
auto di_builder = llvm::unwrap(builder);
|
||||
std::vector<int64_t> expression;
|
||||
for (uint64_t i = 0; i < exprCount; ++i)
|
||||
expression.push_back(expr[i]);
|
||||
di_builder->insertDeclare(llvm::unwrap(value),
|
||||
llvm::unwrap(localVariable),
|
||||
di_builder->createExpression(expression),
|
||||
llvm::unwrap(location),
|
||||
llvm::unwrap(bb));
|
||||
}
|
||||
|
||||
DILocationRef LLVMCreateLocation(LLVMContextRef contextRef, unsigned line,
|
||||
unsigned col, DIScopeOpaqueRef scope) {
|
||||
auto location = llvm::DILocation::get(*llvm::unwrap(contextRef), line, col, llvm::unwrap(scope), nullptr);
|
||||
return llvm::wrap(location);
|
||||
}
|
||||
|
||||
DILocationRef LLVMCreateLocationInlinedAt(LLVMContextRef contextRef, unsigned line,
|
||||
unsigned col, DIScopeOpaqueRef scope, DILocationRef refLocationInlinedAt) {
|
||||
auto location = llvm::DILocation::get(*llvm::unwrap(contextRef), line, col, llvm::unwrap(scope), llvm::unwrap(refLocationInlinedAt));
|
||||
return llvm::wrap(location);
|
||||
}
|
||||
|
||||
void LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, DILocationRef refLocation) {
|
||||
llvm::unwrap(builder)->SetCurrentDebugLocation(llvm::unwrap(refLocation));
|
||||
}
|
||||
|
||||
void LLVMBuilderResetDebugLocation(LLVMBuilderRef builder) {
|
||||
llvm::unwrap(builder)->SetCurrentDebugLocation(nullptr);
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMBuilderGetCurrentFunction(LLVMBuilderRef builder) {
|
||||
return llvm::wrap(llvm::unwrap(builder)->GetInsertBlock()->getParent());
|
||||
}
|
||||
|
||||
const char* LLVMBuilderGetCurrentBbName(LLVMBuilderRef builder) {
|
||||
return llvm::unwrap(builder)->GetInsertBlock()->getName().str().c_str();
|
||||
}
|
||||
|
||||
|
||||
const char *DIGetSubprogramLinkName(DISubprogramRef sp) {
|
||||
return llvm::unwrap(sp)->getLinkageName().str().c_str();
|
||||
}
|
||||
|
||||
int DISubprogramDescribesFunction(DISubprogramRef sp, LLVMValueRef fn) {
|
||||
return llvm::unwrap(sp)->describes(llvm::cast<llvm::Function>(llvm::unwrap(fn)));
|
||||
}
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_INFO_C_H__
|
||||
# define __DEBUG_INFO_C_H__
|
||||
#include <llvm-c/Core.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
typedef struct LLVMOpaqueDIBuilder *DIBuilderRef;
|
||||
//typedef struct DIBuilder *DIBuilderRef;
|
||||
typedef struct DICompileUnit *DICompileUnitRef;
|
||||
typedef struct DIFile *DIFileRef;
|
||||
typedef struct DIBasicType *DIBasicTypeRef;
|
||||
typedef struct DICompositeType *DICompositeTypeRef;
|
||||
typedef struct DIDerivedType *DIDerivedTypeRef;
|
||||
typedef struct DIType *DITypeOpaqueRef;
|
||||
typedef struct DISubprogram *DISubprogramRef;
|
||||
typedef struct DIModule *DIModuleRef;
|
||||
typedef struct DIScope *DIScopeOpaqueRef;
|
||||
typedef struct DISubroutineType *DISubroutineTypeRef;
|
||||
//typedef struct DISubprogram *DISubprogramRef;
|
||||
typedef struct DILocation *DILocationRef;
|
||||
typedef struct DILocalVariable *DILocalVariableRef;
|
||||
typedef struct DIExpression *DIExpressionRef;
|
||||
|
||||
void DIFinalize(DIBuilderRef builder);
|
||||
|
||||
DICompileUnitRef DICreateCompilationUnit(DIBuilderRef builder, unsigned int lang, const char *File, const char* dir, const char * producer, int isOptimized, const char * flags, unsigned int rv);
|
||||
|
||||
DIFileRef DICreateFile(DIBuilderRef builder, const char *filename, const char *directory);
|
||||
|
||||
DIBasicTypeRef DICreateBasicType(DIBuilderRef builder, const char* name, uint64_t sizeInBits, uint64_t alignment, unsigned encoding);
|
||||
|
||||
DICompositeTypeRef DICreateStructType(DIBuilderRef refBuilder,
|
||||
DIScopeOpaqueRef scope, const char *name,
|
||||
DIFileRef file, unsigned lineNumber,
|
||||
uint64_t sizeInBits, uint64_t alignInBits,
|
||||
unsigned flags, DITypeOpaqueRef derivedFrom,
|
||||
DIDerivedTypeRef *elements,
|
||||
uint64_t elementsCount,
|
||||
DICompositeTypeRef refPlace);
|
||||
DICompositeTypeRef DICreateArrayType(DIBuilderRef refBuilder,
|
||||
uint64_t size, uint64_t alignInBits,
|
||||
DITypeOpaqueRef type,
|
||||
uint64_t elementsCount);
|
||||
|
||||
DIDerivedTypeRef DICreateReferenceType(DIBuilderRef refBuilder, DITypeOpaqueRef refType);
|
||||
DIDerivedTypeRef DICreatePointerType(DIBuilderRef refBuilder, DITypeOpaqueRef refType);
|
||||
DICompositeTypeRef DICreateReplaceableCompositeType(DIBuilderRef refBuilder,
|
||||
int tag,
|
||||
const char *name,
|
||||
DIScopeOpaqueRef refScope,
|
||||
DIFileRef refFile,
|
||||
unsigned line);
|
||||
DIDerivedTypeRef DICreateMemberType(DIBuilderRef refBuilder,
|
||||
DIScopeOpaqueRef refScope,
|
||||
const char *name,
|
||||
DIFileRef file,
|
||||
unsigned lineNum,
|
||||
uint64_t sizeInBits,
|
||||
uint64_t alignInBits,
|
||||
uint64_t offsetInBits,
|
||||
unsigned flags,
|
||||
DITypeOpaqueRef type);
|
||||
|
||||
|
||||
DIModuleRef DICreateModule(DIBuilderRef builder, DIScopeOpaqueRef scope,
|
||||
const char* name, const char* configurationMacro,
|
||||
const char* includePath, const char *iSysRoot);
|
||||
|
||||
DIScopeOpaqueRef DICreateLexicalBlockFile(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef);
|
||||
|
||||
DIScopeOpaqueRef DICreateLexicalBlock(DIBuilderRef builderRef, DIScopeOpaqueRef scopeRef, DIFileRef fileRef, int line, int column);
|
||||
|
||||
DISubprogramRef DICreateFunction(DIBuilderRef builder, DIScopeOpaqueRef scope,
|
||||
const char* name, const char *linkageName,
|
||||
DIFileRef file, unsigned lineNo,
|
||||
DISubroutineTypeRef type, int isLocal,
|
||||
int isDefinition, unsigned scopeLine);
|
||||
|
||||
DISubroutineTypeRef DICreateSubroutineType(DIBuilderRef builder,
|
||||
DITypeOpaqueRef* types,
|
||||
unsigned typesCount);
|
||||
|
||||
DILocalVariableRef DICreateAutoVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, DIFileRef file, unsigned line, DITypeOpaqueRef type);
|
||||
DILocalVariableRef DICreateParameterVariable(DIBuilderRef builder, DIScopeOpaqueRef scope, const char *name, unsigned argNo, DIFileRef file, unsigned line, DITypeOpaqueRef type);
|
||||
void DIInsertDeclaration(DIBuilderRef builder, LLVMValueRef value, DILocalVariableRef localVariable, DILocationRef location, LLVMBasicBlockRef bb, int64_t *expr, uint64_t exprCount);
|
||||
DIExpressionRef DICreateEmptyExpression(DIBuilderRef builder);
|
||||
void DIFunctionAddSubprogram(LLVMValueRef fn, DISubprogramRef sp);
|
||||
DILocationRef LLVMCreateLocation(LLVMContextRef contextRef, unsigned line, unsigned col, DIScopeOpaqueRef scope);
|
||||
DILocationRef LLVMCreateLocationInlinedAt(LLVMContextRef contextRef, unsigned line, unsigned col, DIScopeOpaqueRef scope, DILocationRef refLocation);
|
||||
void LLVMBuilderSetDebugLocation(LLVMBuilderRef builder, DILocationRef refLocation);
|
||||
void LLVMBuilderResetDebugLocation(LLVMBuilderRef builder);
|
||||
const char* LLVMBuilderGetCurrentBbName(LLVMBuilderRef builder);
|
||||
const char *DIGetSubprogramLinkName(DISubprogramRef sp);
|
||||
LLVMValueRef LLVMBuilderGetCurrentFunction(LLVMBuilderRef builder);
|
||||
int DISubprogramDescribesFunction(DISubprogramRef sp, LLVMValueRef fn);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,490 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
##
|
||||
# Copyright 2010-2017 JetBrains s.r.o.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# (lldb) command script import llvmDebugInfoC/src/scripts/konan_lldb.py
|
||||
# (lldb) p kotlin_variable
|
||||
#
|
||||
|
||||
import lldb
|
||||
import struct
|
||||
import re
|
||||
import sys
|
||||
|
||||
NULL = 'null'
|
||||
|
||||
def log(msg):
|
||||
if False:
|
||||
print(msg(), file=sys.stderr)
|
||||
|
||||
def exelog(stmt):
|
||||
if False:
|
||||
f = open(os.getenv('HOME', '') + "/lldbexelog.txt", "a")
|
||||
f.write(stmt())
|
||||
f.write("\n")
|
||||
f.close()
|
||||
|
||||
def lldb_val_to_ptr(lldb_val):
|
||||
addr = lldb_val.GetValueAsUnsigned()
|
||||
return '((struct ObjHeader *) {:#x})'.format(addr)
|
||||
|
||||
|
||||
def evaluate(expr):
|
||||
result = lldb.debugger.GetSelectedTarget().EvaluateExpression(expr, lldb.SBExpressionOptions())
|
||||
evallog = lambda : "{} => {}".format(expr, result)
|
||||
log(evallog)
|
||||
exelog(evallog)
|
||||
return result
|
||||
|
||||
def _symbol_loaded_address(name, debugger = lldb.debugger):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
candidates = list(filter(lambda x: x.name == name, frame.module.symbols))
|
||||
# take first
|
||||
for candidate in candidates:
|
||||
address = candidate.GetStartAddress().GetLoadAddress(target)
|
||||
log(lambda: "_symbol_loaded_address:{} {:#x}".format(name, address))
|
||||
return address
|
||||
|
||||
def _type_info_by_address(address, debugger = lldb.debugger):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
candidates = list(filter(lambda x: x.GetStartAddress().GetLoadAddress(target) == address, frame.module.symbols))
|
||||
return candidates
|
||||
|
||||
def is_instance_of(addr, typeinfo):
|
||||
return evaluate("(bool)IsInstance({}, {:#x})".format(addr, typeinfo)).GetValue() == "true"
|
||||
|
||||
def is_string_or_array(value):
|
||||
return evaluate("(int)IsInstance({0}, {1}) ? 1 : ((int)Konan_DebugIsArray({0}) ? 2 : 0)".format(lldb_val_to_ptr(value), _symbol_loaded_address('kclass:kotlin.String'))).unsigned
|
||||
|
||||
def type_info(value):
|
||||
"""This method checks self-referencing of pointer of first member of TypeInfo including case when object has an
|
||||
meta-object pointed by TypeInfo. Two lower bits are reserved for memory management needs see runtime/src/main/cpp/Memory.h."""
|
||||
if value.GetTypeName() != "ObjHeader *":
|
||||
return False
|
||||
expr = "*(void **)((uintptr_t)(*(void**){0:#x}) & ~0x3) == **(void***)((uintptr_t)(*(void**){0:#x}) & ~0x3) ? *(void **)((uintptr_t)(*(void**){0:#x}) & ~0x3) : (void *)0".format(value.unsigned)
|
||||
result = evaluate(expr)
|
||||
return result.unsigned if result.IsValid() and result.unsigned != 0 else None
|
||||
|
||||
|
||||
__FACTORY = {}
|
||||
|
||||
|
||||
# Cache type info pointer to [ChildMetaInfo]
|
||||
SYNTHETIC_OBJECT_LAYOUT_CACHE = {}
|
||||
TO_STRING_DEPTH = 2
|
||||
ARRAY_TO_STRING_LIMIT = 10
|
||||
|
||||
def kotlin_object_type_summary(lldb_val, internal_dict = {}):
|
||||
"""Hook that is run by lldb to display a Kotlin object."""
|
||||
log(lambda: "kotlin_object_type_summary({:#x}, {})".format(lldb_val.unsigned, internal_dict))
|
||||
fallback = lldb_val.GetValue()
|
||||
if str(lldb_val.type) != "struct ObjHeader *":
|
||||
if lldb_val.GetValue() is None:
|
||||
return NULL
|
||||
return lldb_val.GetValueAsSigned()
|
||||
|
||||
if lldb_val.unsigned == 0:
|
||||
return NULL
|
||||
tip = internal_dict["type_info"] if "type_info" in internal_dict.keys() else type_info(lldb_val)
|
||||
|
||||
if not tip:
|
||||
return fallback
|
||||
|
||||
return select_provider(lldb_val, tip, internal_dict).to_string()
|
||||
|
||||
|
||||
def select_provider(lldb_val, tip, internal_dict):
|
||||
log(lambda : "select_provider: name:{} : {}, {}".format(lldb_val.name, lldb_val, internal_dict))
|
||||
soa = is_string_or_array(lldb_val)
|
||||
log(lambda : "select_provider: {} : soa: {}".format(lldb_val, soa))
|
||||
return __FACTORY['string'](lldb_val, tip, internal_dict) if soa == 1 else __FACTORY['array'](lldb_val, tip, internal_dict) if soa == 2 \
|
||||
else __FACTORY['object'](lldb_val, tip, internal_dict)
|
||||
|
||||
class KonanHelperProvider(lldb.SBSyntheticValueProvider):
|
||||
def __init__(self, valobj, amString, internal_dict = {}):
|
||||
self._target = lldb.debugger.GetSelectedTarget()
|
||||
self._process = self._target.GetProcess()
|
||||
self._valobj = valobj
|
||||
self._ptr = lldb_val_to_ptr(self._valobj)
|
||||
if amString:
|
||||
return
|
||||
self._internal_dict = internal_dict.copy()
|
||||
self._to_string_depth = TO_STRING_DEPTH if "to_string_depth" not in self._internal_dict.keys() else self._internal_dict["to_string_depth"]
|
||||
if self._children_count == 0:
|
||||
self._children_count = evaluate("(int)Konan_DebugGetFieldCount({})".format(self._ptr)).signed
|
||||
self._children = []
|
||||
self._type_conversion = [
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(void *){:#x}".format(address)),
|
||||
lambda address, name: self._create_synthetic_child(address, name),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int8_t *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int16_t *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int32_t *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(int64_t *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(float *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(double *){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(void **){:#x}".format(address)),
|
||||
lambda address, name: self._valobj.CreateValueFromExpression(name, "(bool *){:#x}".format(address)),
|
||||
lambda address, name: None]
|
||||
|
||||
self._types = [
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(),
|
||||
valobj.GetType(),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeChar),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeShort),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeInt),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeFloat),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeDouble),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType(),
|
||||
valobj.GetType().GetBasicType(lldb.eBasicTypeBool)
|
||||
]
|
||||
|
||||
def _read_string(self, expr, error):
|
||||
return self._process.ReadCStringFromMemory(evaluate(expr).unsigned, 0x1000, error)
|
||||
|
||||
def _read_value(self, index):
|
||||
value_type = self._children[index].type()
|
||||
address = self._valobj.unsigned + self._children[index].offset()
|
||||
return self._type_conversion[int(value_type)](address, str(self._children[index].name()))
|
||||
|
||||
def _create_synthetic_child(self, address, name):
|
||||
if self._to_string_depth == 0:
|
||||
return None
|
||||
index = self.get_child_index(name)
|
||||
value = self._valobj.CreateChildAtOffset(str(name),
|
||||
self._children[index].offset(),
|
||||
self._read_type(index))
|
||||
value.SetSyntheticChildrenGenerated(True)
|
||||
value.SetPreferSyntheticValue(True)
|
||||
return value
|
||||
|
||||
def _read_type(self, index):
|
||||
type = self._types[self._children[index].type()]
|
||||
log(lambda: "type:{0} of {1:#x} of {2:#x}".format(type, self._valobj.unsigned, self._valobj.unsigned + self._children[index].offset()))
|
||||
return type
|
||||
|
||||
def _deref_or_obj_summary(self, index, internal_dict):
|
||||
value = self._values[index]
|
||||
if not value:
|
||||
log(lambda : "_deref_or_obj_summary: value none, index:{}, type:{}".format(index, self._children[index].type()))
|
||||
return None
|
||||
|
||||
tip = type_info(value)
|
||||
if tip:
|
||||
internal_dict["type_info"] = tip
|
||||
return kotlin_object_type_summary(value, internal_dict)
|
||||
tip = type_info(value.deref)
|
||||
|
||||
if tip:
|
||||
internal_dict["type_info"] = tip
|
||||
return kotlin_object_type_summary(value.deref, internal_dict)
|
||||
|
||||
return kotlin_object_type_summary(value.deref, internal_dict)
|
||||
|
||||
def _field_address(self, index):
|
||||
return evaluate("(void *)Konan_DebugGetFieldAddress({}, {})".format(self._ptr, index)).unsigned
|
||||
|
||||
def _field_type(self, index):
|
||||
return evaluate("(int)Konan_DebugGetFieldType({}, {})".format(self._ptr, index)).unsigned
|
||||
|
||||
class KonanStringSyntheticProvider(KonanHelperProvider):
|
||||
def __init__(self, valobj):
|
||||
self._children_count = 0
|
||||
super(KonanStringSyntheticProvider, self).__init__(valobj, True)
|
||||
fallback = valobj.GetValue()
|
||||
buff_addr = evaluate("(void *)Konan_DebugBuffer()").unsigned
|
||||
buff_len = evaluate(
|
||||
'(int)Konan_DebugObjectToUtf8Array({}, (void *){:#x}, (int)Konan_DebugBufferSize());'.format(
|
||||
self._ptr, buff_addr)
|
||||
).signed
|
||||
|
||||
if not buff_len:
|
||||
self._representation = fallback
|
||||
return
|
||||
|
||||
error = lldb.SBError()
|
||||
s = self._process.ReadCStringFromMemory(int(buff_addr), int(buff_len), error)
|
||||
if not error.Success():
|
||||
raise DebuggerException()
|
||||
self._representation = s if error.Success() else fallback
|
||||
self._logger = lldb.formatters.Logger.Logger()
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
def num_children(self):
|
||||
return 0
|
||||
|
||||
def has_children(self):
|
||||
return False
|
||||
|
||||
def get_child_index(self, _):
|
||||
return None
|
||||
|
||||
def get_child_at_index(self, _):
|
||||
return None
|
||||
|
||||
def to_string(self):
|
||||
return self._representation
|
||||
|
||||
|
||||
class DebuggerException(Exception):
|
||||
pass
|
||||
|
||||
class MemberLayout:
|
||||
def __init__(self, name, type, offset):
|
||||
self._name = name
|
||||
self._type = type
|
||||
self._offset = offset
|
||||
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
def offset(self):
|
||||
return self._offset
|
||||
|
||||
class KonanObjectSyntheticProvider(KonanHelperProvider):
|
||||
def __init__(self, valobj, tip, internal_dict):
|
||||
# Save an extra call into the process
|
||||
if tip in SYNTHETIC_OBJECT_LAYOUT_CACHE:
|
||||
log(lambda : "TIP: {:#x} EARLYHIT".format(tip))
|
||||
self._children = SYNTHETIC_OBJECT_LAYOUT_CACHE[tip]
|
||||
self._children_count = len(self._children)
|
||||
else:
|
||||
self._children_count = 0
|
||||
|
||||
super(KonanObjectSyntheticProvider, self).__init__(valobj, False, internal_dict)
|
||||
|
||||
if not tip in SYNTHETIC_OBJECT_LAYOUT_CACHE:
|
||||
SYNTHETIC_OBJECT_LAYOUT_CACHE[tip] = [
|
||||
MemberLayout(self._field_name(i), self._field_type(i), self._field_address(i) - self._valobj.unsigned)
|
||||
for i in range(self._children_count)]
|
||||
log(lambda : "TIP: {:#x} MISSED".format(tip))
|
||||
else:
|
||||
log(lambda : "TIP: {:#x} HIT".format(tip))
|
||||
self._children = SYNTHETIC_OBJECT_LAYOUT_CACHE[tip]
|
||||
self._values = [self._read_value(index) for index in range(self._children_count)]
|
||||
|
||||
|
||||
def _field_name(self, index):
|
||||
error = lldb.SBError()
|
||||
name = self._read_string("(void *)Konan_DebugGetFieldName({}, (int){})".format(self._ptr, index), error)
|
||||
if not error.Success():
|
||||
raise DebuggerException()
|
||||
return name
|
||||
|
||||
def num_children(self):
|
||||
return self._children_count
|
||||
|
||||
def has_children(self):
|
||||
return self._children_count > 0
|
||||
|
||||
def get_child_index(self, name):
|
||||
def __none(iterable, f):
|
||||
return not any(f(x) for x in iterable)
|
||||
if __none(self._children, lambda x: x.name() == name):
|
||||
return -1
|
||||
return next(i for i,v in enumerate(self._children) if v.name() == name)
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
result = self._values[index]
|
||||
if result is None:
|
||||
result = self._read_value(index)
|
||||
self._values[index] = result
|
||||
return result
|
||||
|
||||
|
||||
# TODO: fix cyclic structures stringification.
|
||||
def to_string(self):
|
||||
if self._to_string_depth == 0:
|
||||
return "..."
|
||||
else:
|
||||
internal_dict = self._internal_dict.copy()
|
||||
internal_dict["to_string_depth"] = self._to_string_depth - 1
|
||||
return dict([(self._children[i].name(), self._deref_or_obj_summary(i, internal_dict)) for i in range(self._children_count)])
|
||||
|
||||
class KonanArraySyntheticProvider(KonanHelperProvider):
|
||||
def __init__(self, valobj, internal_dict):
|
||||
self._children_count = 0
|
||||
super(KonanArraySyntheticProvider, self).__init__(valobj, False, internal_dict)
|
||||
if self._ptr is None:
|
||||
return
|
||||
valobj.SetSyntheticChildrenGenerated(True)
|
||||
type = self._field_type(0)
|
||||
zerro_address = self._field_address(0)
|
||||
first_address = self._field_address(1)
|
||||
offset = zerro_address - valobj.unsigned
|
||||
size = first_address - zerro_address
|
||||
self._children = [MemberLayout(str(x), type, offset + x * size) for x in range(self.num_children())]
|
||||
self._values = [self._read_value(i) for i in range(min(ARRAY_TO_STRING_LIMIT, self._children_count))]
|
||||
|
||||
|
||||
def cap_children_count(self):
|
||||
return self._children_count
|
||||
|
||||
def num_children(self):
|
||||
return self.cap_children_count()
|
||||
|
||||
def has_children(self):
|
||||
return self._children_count > 0
|
||||
|
||||
def get_child_index(self, name):
|
||||
index = int(name)
|
||||
return index if (0 <= index < self._children_count) else -1
|
||||
|
||||
def get_child_at_index(self, index):
|
||||
result = self._values[index]
|
||||
if result is None:
|
||||
result = self._read_value(index)
|
||||
self._values[index] = result
|
||||
return result
|
||||
|
||||
def to_string(self):
|
||||
return [self._deref_or_obj_summary(i, self._internal_dict.copy()) for i in range(min(ARRAY_TO_STRING_LIMIT, self._children_count))]
|
||||
|
||||
|
||||
class KonanProxyTypeProvider:
|
||||
def __init__(self, valobj, internal_dict):
|
||||
log(lambda : "KonanProxyTypeProvider: {:#x}".format(valobj.unsigned))
|
||||
tip = type_info(valobj)
|
||||
|
||||
if not tip:
|
||||
return
|
||||
log(lambda : "KonanProxyTypeProvider: tip: {:#x}".format(tip))
|
||||
self._proxy = select_provider(valobj, tip, internal_dict)
|
||||
log(lambda: "KonanProxyTypeProvider: _proxy: {}".format(self._proxy.__class__.__name__))
|
||||
self.update()
|
||||
|
||||
def __getattr__(self, item):
|
||||
return getattr(self._proxy, item)
|
||||
|
||||
def clear_cache_command(debugger, command, result, internal_dict):
|
||||
SYNTHETIC_OBJECT_LAYOUT_CACHE.clear()
|
||||
|
||||
|
||||
def type_name_command(debugger, command, result, internal_dict):
|
||||
result.AppendMessage(evaluate('(char *)Konan_DebugGetTypeName({})'.format(command)).summary)
|
||||
|
||||
__KONAN_VARIABLE = re.compile('kvar:(.*)#internal')
|
||||
__KONAN_VARIABLE_TYPE = re.compile('^kfun:<get-(.*)>\\(\\)(.*)$')
|
||||
__TYPES_KONAN_TO_C = {
|
||||
'kotlin.Byte': ('int8_t', lambda v: v.signed),
|
||||
'kotlin.Short': ('short', lambda v: v.signed),
|
||||
'kotlin.Int': ('int', lambda v: v.signed),
|
||||
'kotlin.Long': ('long', lambda v: v.signed),
|
||||
'kotlin.UByte': ('int8_t', lambda v: v.unsigned),
|
||||
'kotlin.UShort': ('short', lambda v: v.unsigned),
|
||||
'kotlin.UInt': ('int', lambda v: v.unsigned),
|
||||
'kotlin.ULong': ('long', lambda v: v.unsigned),
|
||||
'kotlin.Char': ('short', lambda v: v.signed),
|
||||
'kotlin.Boolean': ('bool', lambda v: v.signed),
|
||||
'kotlin.Float': ('float', lambda v: v.value),
|
||||
'kotlin.Double': ('double', lambda v: v.value)
|
||||
}
|
||||
|
||||
def type_by_address_command(debugger, command, result, internal_dict):
|
||||
result.AppendMessage("DEBUG: {}".format(command))
|
||||
tokens = command.split()
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
types = _type_info_by_address(tokens[0])
|
||||
result.AppendMessage("DEBUG: {}".format(types))
|
||||
for t in types:
|
||||
result.AppendMessage("{}: {:#x}".format(t.name, t.GetStartAddress().GetLoadAddress(target)))
|
||||
|
||||
def symbol_by_name_command(debugger, command, result, internal_dict):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
tokens = command.split()
|
||||
mask = re.compile(tokens[0])
|
||||
symbols = list(filter(lambda v: mask.match(v.name), frame.GetModule().symbols))
|
||||
visited = list()
|
||||
for symbol in symbols:
|
||||
name = symbol.name
|
||||
if name in visited:
|
||||
continue
|
||||
visited.append(name)
|
||||
result.AppendMessage("{}: {:#x}".format(name, symbol.GetStartAddress().GetLoadAddress(target)))
|
||||
|
||||
def konan_globals_command(debugger, command, result, internal_dict):
|
||||
target = debugger.GetSelectedTarget()
|
||||
process = target.GetProcess()
|
||||
thread = process.GetSelectedThread()
|
||||
frame = thread.GetSelectedFrame()
|
||||
|
||||
konan_variable_symbols = list(filter(lambda v: __KONAN_VARIABLE.match(v.name), frame.GetModule().symbols))
|
||||
visited = list()
|
||||
for symbol in konan_variable_symbols:
|
||||
name = __KONAN_VARIABLE.search(symbol.name).group(1)
|
||||
|
||||
if name in visited:
|
||||
continue
|
||||
visited.append(name)
|
||||
|
||||
getters = list(filter(lambda v: re.match('^kfun:<get-{}>\\(\\).*$'.format(name), v.name), frame.module.symbols))
|
||||
if not getters:
|
||||
result.AppendMessage("storage not found for name:{}".format(name))
|
||||
continue
|
||||
|
||||
getter_functions = frame.module.FindFunctions(getters[0].name)
|
||||
if not getter_functions:
|
||||
continue
|
||||
|
||||
address = getter_functions[0].function.GetStartAddress().GetLoadAddress(target)
|
||||
type = __KONAN_VARIABLE_TYPE.search(getters[0].name).group(2)
|
||||
(c_type, extractor) = __TYPES_KONAN_TO_C[type] if type in __TYPES_KONAN_TO_C.keys() else ('struct ObjHeader *', lambda v: kotlin_object_type_summary(v))
|
||||
value = evaluate('(({0} (*)()){1:#x})()'.format(c_type, address))
|
||||
str_value = extractor(value)
|
||||
result.AppendMessage('{} {}: {}'.format(type, name, str_value))
|
||||
|
||||
def __lldb_init_module(debugger, _):
|
||||
__FACTORY['object'] = lambda x, y, z: KonanObjectSyntheticProvider(x, y, z)
|
||||
__FACTORY['array'] = lambda x, y, z: KonanArraySyntheticProvider(x, z)
|
||||
__FACTORY['string'] = lambda x, y, _: KonanStringSyntheticProvider(x)
|
||||
debugger.HandleCommand('\
|
||||
type summary add \
|
||||
--no-value \
|
||||
--expand \
|
||||
--python-function konan_lldb.kotlin_object_type_summary \
|
||||
"struct ObjHeader *" \
|
||||
--category Kotlin\
|
||||
')
|
||||
debugger.HandleCommand('\
|
||||
type synthetic add \
|
||||
--python-class konan_lldb.KonanProxyTypeProvider\
|
||||
"ObjHeader *" \
|
||||
--category Kotlin\
|
||||
')
|
||||
debugger.HandleCommand('type category enable Kotlin')
|
||||
debugger.HandleCommand('command script add -f {}.clear_cache_command clear_kotlin_cache'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.type_name_command type_name'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.type_by_address_command type_by_address'.format(__name__))
|
||||
debugger.HandleCommand('command script add -f {}.symbol_by_name_command symbol_by_name'.format(__name__))
|
||||
|
||||
Reference in New Issue
Block a user