You've already forked linux-packaging-mono
Imported Upstream version 5.14.0.78
Former-commit-id: 3494343bcc9ddb42b36b82dd9ae7b69e85e0229f
This commit is contained in:
parent
74b74abd9f
commit
19234507ba
@@ -47,6 +47,7 @@ extern "C" Object * __allocate_array(size_t elements, MethodTable * pMT);
|
||||
extern "C" Object * __castclass(void * obj, MethodTable * pMT);
|
||||
extern "C" Object * __isinst(void * obj, MethodTable * pMT);
|
||||
extern "C" __NORETURN void __throw_exception(void * pEx);
|
||||
extern "C" void __debug_break();
|
||||
|
||||
Object * __load_string_literal(const char * string);
|
||||
|
||||
|
||||
10
external/corert/src/Native/Bootstrap/main.cpp
vendored
10
external/corert/src/Native/Bootstrap/main.cpp
vendored
@@ -98,6 +98,7 @@ extern "C" void * RhTypeCast_CheckCast(void * pObject, MethodTable * pMT);
|
||||
extern "C" void RhpStelemRef(void * pArray, int index, void * pObj);
|
||||
extern "C" void * RhpLdelemaRef(void * pArray, int index, MethodTable * pMT);
|
||||
extern "C" __NORETURN void RhpThrowEx(void * pEx);
|
||||
extern "C" void RhDebugBreak();
|
||||
|
||||
extern "C" Object * __allocate_object(MethodTable * pMT)
|
||||
{
|
||||
@@ -134,6 +135,11 @@ extern "C" void __throw_exception(void * pEx)
|
||||
RhpThrowEx(pEx);
|
||||
}
|
||||
|
||||
extern "C" void __debug_break()
|
||||
{
|
||||
RhDebugBreak();
|
||||
}
|
||||
|
||||
void __range_check_fail()
|
||||
{
|
||||
throw "ThrowRangeOverflowException";
|
||||
@@ -288,7 +294,9 @@ static const pfn c_classlibFunctions[] = {
|
||||
&AppendExceptionStackFrame,
|
||||
nullptr, // &CheckStaticClassConstruction,
|
||||
&GetSystemArrayEEType,
|
||||
&OnFirstChanceException
|
||||
&OnFirstChanceException,
|
||||
nullptr, // &DebugFuncEvalHelper,
|
||||
nullptr, // &DebugFuncEvalAbortHelper,
|
||||
};
|
||||
|
||||
#endif // !CPPCODEGEN
|
||||
|
||||
118
external/corert/src/Native/ObjWriter/llvm.patch
vendored
118
external/corert/src/Native/ObjWriter/llvm.patch
vendored
@@ -1,5 +1,5 @@
|
||||
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
|
||||
index 7c1189e46ab..d1d77c97311 100644
|
||||
index 7c1189e..d1d77c9 100644
|
||||
--- a/include/llvm/MC/MCObjectStreamer.h
|
||||
+++ b/include/llvm/MC/MCObjectStreamer.h
|
||||
@@ -101,6 +101,11 @@ public:
|
||||
@@ -14,8 +14,20 @@ index 7c1189e46ab..d1d77c97311 100644
|
||||
/// \brief Emit an instruction to a special fragment, because this instruction
|
||||
/// can change its size during relaxation.
|
||||
virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
|
||||
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
|
||||
index 5390e79..e28a3cc 100644
|
||||
--- a/include/llvm/MC/MCStreamer.h
|
||||
+++ b/include/llvm/MC/MCStreamer.h
|
||||
@@ -115,6 +115,7 @@ public:
|
||||
virtual void emitPad(int64_t Offset);
|
||||
virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
bool isVector);
|
||||
+ virtual void emitLsda(const MCSymbol *Symbol);
|
||||
virtual void emitUnwindRaw(int64_t StackOffset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes);
|
||||
|
||||
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
|
||||
index 174397e2739..ef7161fb56c 100644
|
||||
index 174397e..ef7161f 100644
|
||||
--- a/lib/MC/MCObjectStreamer.cpp
|
||||
+++ b/lib/MC/MCObjectStreamer.cpp
|
||||
@@ -122,7 +122,7 @@ void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) {
|
||||
@@ -46,7 +58,7 @@ index 174397e2739..ef7161fb56c 100644
|
||||
// We need to create a local symbol to avoid relocations.
|
||||
Frame.Begin = getContext().createTempSymbol();
|
||||
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
|
||||
index a77df7a2598..e1aa7526f9b 100644
|
||||
index a77df7a..e1aa752 100644
|
||||
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
|
||||
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
|
||||
@@ -48,6 +48,14 @@ public:
|
||||
@@ -84,7 +96,7 @@ index a77df7a2598..e1aa7526f9b 100644
|
||||
return 2;
|
||||
case FK_SecRel_4:
|
||||
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
|
||||
index 02374966daf..01676a01683 100644
|
||||
index 0237496..01676a0 100644
|
||||
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
|
||||
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
@@ -96,7 +108,7 @@ index 02374966daf..01676a01683 100644
|
||||
|
||||
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
|
||||
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
|
||||
index 59f31be69d5..9b95598f99f 100644
|
||||
index 59f31be..9b95598 100644
|
||||
--- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
|
||||
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
|
||||
@@ -103,6 +103,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
@@ -109,8 +121,102 @@ index 59f31be69d5..9b95598f99f 100644
|
||||
case ARM::fixup_arm_blx:
|
||||
case ARM::fixup_arm_uncondbl:
|
||||
switch (Modifier) {
|
||||
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
|
||||
index 93f4006..67ae439 100644
|
||||
--- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
|
||||
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
|
||||
@@ -396,6 +396,7 @@ private:
|
||||
void emitPad(int64_t Offset) override;
|
||||
void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
bool isVector) override;
|
||||
+ void emitLsda(const MCSymbol *Symbol) override;
|
||||
void emitUnwindRaw(int64_t Offset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes) override;
|
||||
|
||||
@@ -461,6 +462,7 @@ public:
|
||||
void emitMovSP(unsigned Reg, int64_t Offset = 0);
|
||||
void emitPad(int64_t Offset);
|
||||
void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
|
||||
+ void emitLsda(const MCSymbol *Symbol);
|
||||
void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
|
||||
|
||||
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override {
|
||||
@@ -698,6 +700,7 @@ private:
|
||||
bool CantUnwind;
|
||||
SmallVector<uint8_t, 64> Opcodes;
|
||||
UnwindOpcodeAssembler UnwindOpAsm;
|
||||
+ const MCSymbol *Lsda;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@@ -740,6 +743,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
getStreamer().emitRegSave(RegList, isVector);
|
||||
}
|
||||
|
||||
+void ARMTargetELFStreamer::emitLsda(const MCSymbol *Symbol) {
|
||||
+ getStreamer().emitLsda(Symbol);
|
||||
+}
|
||||
+
|
||||
void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes) {
|
||||
getStreamer().emitUnwindRaw(Offset, Opcodes);
|
||||
@@ -1233,6 +1240,7 @@ void ARMELFStreamer::EHReset() {
|
||||
PendingOffset = 0;
|
||||
UsedFP = false;
|
||||
CantUnwind = false;
|
||||
+ Lsda = nullptr;
|
||||
|
||||
Opcodes.clear();
|
||||
UnwindOpAsm.Reset();
|
||||
@@ -1330,6 +1338,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
|
||||
}
|
||||
|
||||
// Finalize the unwind opcode sequence
|
||||
+ if (Lsda != nullptr && Opcodes.size() <= 4u)
|
||||
+ PersonalityIndex = ARM::EHABI::AEABI_UNWIND_CPP_PR1;
|
||||
UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
|
||||
|
||||
// For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
|
||||
@@ -1374,7 +1384,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
|
||||
//
|
||||
// In case that the .handlerdata directive is not specified by the
|
||||
// programmer, we should emit zero to terminate the handler data.
|
||||
- if (NoHandlerData && !Personality)
|
||||
+ if (Lsda != nullptr) {
|
||||
+ const MCSymbolRefExpr *LsdaRef =
|
||||
+ MCSymbolRefExpr::create(Lsda,
|
||||
+ MCSymbolRefExpr::VK_None,
|
||||
+ getContext());
|
||||
+ EmitValue(LsdaRef, 4);
|
||||
+ } else if (NoHandlerData && !Personality)
|
||||
EmitIntValue(0, 4);
|
||||
}
|
||||
|
||||
@@ -1457,6 +1473,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
UnwindOpAsm.EmitRegSave(Mask);
|
||||
}
|
||||
|
||||
+void ARMELFStreamer::emitLsda(const MCSymbol *Symbol) {
|
||||
+ Lsda = Symbol;
|
||||
+}
|
||||
+
|
||||
void ARMELFStreamer::emitUnwindRaw(int64_t Offset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes) {
|
||||
FlushPendingOffset();
|
||||
diff --git a/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
|
||||
index 4a94318..f4f5aa1 100644
|
||||
--- a/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
|
||||
+++ b/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
|
||||
@@ -61,6 +61,7 @@ void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {}
|
||||
void ARMTargetStreamer::emitPad(int64_t Offset) {}
|
||||
void ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
|
||||
bool isVector) {}
|
||||
+void ARMTargetStreamer::emitLsda(const MCSymbol *Symbol) {}
|
||||
void ARMTargetStreamer::emitUnwindRaw(int64_t StackOffset,
|
||||
const SmallVectorImpl<uint8_t> &Opcodes) {
|
||||
}
|
||||
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
|
||||
index b654b8c5cb8..58d25159af8 100644
|
||||
index b654b8c..58d2515 100644
|
||||
--- a/tools/CMakeLists.txt
|
||||
+++ b/tools/CMakeLists.txt
|
||||
@@ -46,6 +46,7 @@ add_llvm_external_project(clang)
|
||||
|
||||
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.6)
|
||||
project(ObjWriter)
|
||||
include(ExternalProject)
|
||||
|
||||
set(LLVM_VERSION "5")
|
||||
set(OBJWRITER_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../)
|
||||
set(OBJWRITER_LLVM_POINT tools/ObjWriter)
|
||||
|
||||
@@ -36,12 +37,11 @@ if(USE_ARM_TARGET_TRIPLE)
|
||||
list(APPEND LLVM_CMAKE_EXTRA_ARGS "-DLLVM_DEFAULT_TARGET_TRIPLE=thumbv7-linux-gnueabi")
|
||||
endif()
|
||||
|
||||
list(REMOVE_DUPLICATES CORERT_NATIVE_COMPILE_OPTIONS)
|
||||
|
||||
# Make sure to remove debug flags from general build flags for LLVM
|
||||
set(LLVM_COMPILE_OPTIONS "${CORERT_NATIVE_COMPILE_OPTIONS}")
|
||||
list(REMOVE_ITEM LLVM_COMPILE_OPTIONS "-g")
|
||||
list(REMOVE_ITEM LLVM_COMPILE_OPTIONS "-O0")
|
||||
list(REMOVE_ITEM LLVM_COMPILE_OPTIONS "-Werror")
|
||||
|
||||
string(REPLACE ";" "\ " CORERT_NATIVE_COMPILE_OPTIONS "${CORERT_NATIVE_COMPILE_OPTIONS}")
|
||||
string(REPLACE ";" "\ " LLVM_COMPILE_OPTIONS "${LLVM_COMPILE_OPTIONS}")
|
||||
@@ -49,19 +49,32 @@ string(REPLACE ";" "\ " LLVM_COMPILE_OPTIONS "${LLVM_COMPILE_OPTIONS}")
|
||||
# If host and target are the same, we could use llvm-tblgen from LLVM itself.
|
||||
# Otherwise we use host llvm-tblgen. It's universal way for cross-building.
|
||||
if(NOT ${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_SYSTEM_PROCESSOR})
|
||||
execute_process (
|
||||
COMMAND bash -c "echo -n `which llvm-tblgen`"
|
||||
OUTPUT_VARIABLE LLVM_TBLGEN_TOOL
|
||||
)
|
||||
# Find llvm-tblgen tool
|
||||
if(NOT LLVM_TBLGEN_TOOL)
|
||||
message(FATAL_ERROR "Can't find llvm-tblgen. You need to make sure that you have installed LLVM")
|
||||
execute_process (
|
||||
COMMAND bash -c "echo -n `which llvm-tblgen`"
|
||||
OUTPUT_VARIABLE LLVM_TBLGEN_TOOL
|
||||
)
|
||||
if(NOT LLVM_TBLGEN_TOOL)
|
||||
message(FATAL_ERROR "Can't find llvm-tblgen! You need to make sure that you have installed LLVM version $LLVM_VERSION")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check compatibility
|
||||
execute_process (
|
||||
COMMAND bash -c "echo -n `${LLVM_TBLGEN_TOOL} --version | grep -i 'version ${LLVM_VERSION}'`"
|
||||
OUTPUT_VARIABLE IS_LLVM_TBLGEN_TOOL_COMPATIBLE
|
||||
)
|
||||
if(NOT IS_LLVM_TBLGEN_TOOL_COMPATIBLE)
|
||||
message(FATAL_ERROR "LLVM version incompatibility! You need to make sure that you have installed LLVM version ${LLVM_VERSION}")
|
||||
endif()
|
||||
|
||||
list(APPEND LLVM_CMAKE_EXTRA_ARGS "-DLLVM_TABLEGEN=${LLVM_TBLGEN_TOOL}")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(LLVM
|
||||
GIT_REPOSITORY https://github.com/llvm-mirror/llvm
|
||||
GIT_TAG release_50
|
||||
GIT_TAG release_${LLVM_VERSION}0
|
||||
GIT_SHALLOW 1
|
||||
GIT_PROGRESS 1
|
||||
PATCH_COMMAND ""
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
@@ -373,6 +374,11 @@ int ObjectWriter::EmitSymbolRef(const char *SymbolName,
|
||||
Size = 4;
|
||||
IsPCRel = true;
|
||||
break;
|
||||
case RelocType::IMAGE_REL_BASED_RELPTR32:
|
||||
Size = 4;
|
||||
IsPCRel = true;
|
||||
Delta += 4; // size of C# (int) type is always 4 bytes
|
||||
break;
|
||||
case RelocType::IMAGE_REL_BASED_THUMB_MOV32: {
|
||||
const unsigned Offset = GetDFSize();
|
||||
const MCExpr *TargetExpr = GenTargetExpr(SymbolName, Kind, Delta);
|
||||
@@ -837,3 +843,56 @@ ObjectWriter::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberId
|
||||
return TypeBuilder.GetMemberFunctionId(MemberIdDescriptor);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectWriter::EmitARMFnStart() {
|
||||
MCTargetStreamer &TS = *(Streamer->getTargetStreamer());
|
||||
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
|
||||
|
||||
ATS.emitFnStart();
|
||||
}
|
||||
|
||||
void ObjectWriter::EmitARMFnEnd() {
|
||||
MCTargetStreamer &TS = *(Streamer->getTargetStreamer());
|
||||
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
|
||||
|
||||
ATS.emitFnEnd();
|
||||
}
|
||||
|
||||
void ObjectWriter::EmitARMExIdxLsda(const char *LsdaBlobSymbolName)
|
||||
{
|
||||
MCTargetStreamer &TS = *(Streamer->getTargetStreamer());
|
||||
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
|
||||
|
||||
MCSymbol *T = OutContext->getOrCreateSymbol(LsdaBlobSymbolName);
|
||||
Assembler->registerSymbol(*T);
|
||||
|
||||
ATS.emitLsda(T);
|
||||
}
|
||||
|
||||
void ObjectWriter::EmitARMExIdxCode(int Offset, const char *Blob)
|
||||
{
|
||||
MCTargetStreamer &TS = *(Streamer->getTargetStreamer());
|
||||
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
|
||||
SmallVector<unsigned, 4> RegList;
|
||||
|
||||
const CFI_CODE *CfiCode = (const CFI_CODE *)Blob;
|
||||
switch (CfiCode->CfiOpCode) {
|
||||
case CFI_ADJUST_CFA_OFFSET:
|
||||
assert(CfiCode->DwarfReg == DWARF_REG_ILLEGAL &&
|
||||
"Unexpected Register Value for OpAdjustCfaOffset");
|
||||
ATS.emitPad(CfiCode->Offset);
|
||||
break;
|
||||
case CFI_REL_OFFSET:
|
||||
RegList.push_back(CfiCode->DwarfReg);
|
||||
ATS.emitRegSave(RegList, false);
|
||||
break;
|
||||
case CFI_DEF_CFA_REGISTER:
|
||||
assert(CfiCode->Offset == 0 &&
|
||||
"Unexpected Offset Value for OpDefCfaRegister");
|
||||
ATS.emitMovSP(CfiCode->DwarfReg, 0);
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unrecognized CFI");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,8 @@ GetCompleteClassTypeIndex
|
||||
GetArrayTypeIndex
|
||||
GetPointerTypeIndex
|
||||
GetMemberFunctionTypeIndex
|
||||
GetMemberFunctionIdTypeIndex
|
||||
GetMemberFunctionIdTypeIndex
|
||||
EmitARMFnStart
|
||||
EmitARMFnEnd
|
||||
EmitARMExIdxCode
|
||||
EmitARMExIdxLsda
|
||||
84
external/corert/src/Native/ObjWriter/objwriter.h
vendored
84
external/corert/src/Native/ObjWriter/objwriter.h
vendored
@@ -24,6 +24,12 @@
|
||||
using namespace llvm;
|
||||
using namespace llvm::codeview;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_EXPORT extern "C" __attribute((visibility("default")))
|
||||
#endif
|
||||
|
||||
enum CustomSectionAttributes : int32_t {
|
||||
CustomSectionAttributes_ReadOnly = 0x0000,
|
||||
CustomSectionAttributes_Writeable = 0x0001,
|
||||
@@ -38,6 +44,7 @@ enum class RelocType {
|
||||
IMAGE_REL_BASED_DIR64 = 0x0A,
|
||||
IMAGE_REL_BASED_REL32 = 0x10,
|
||||
IMAGE_REL_BASED_THUMB_BRANCH24 = 0x13,
|
||||
IMAGE_REL_BASED_RELPTR32 = 0x7C,
|
||||
};
|
||||
|
||||
class ObjectWriter {
|
||||
@@ -91,6 +98,11 @@ public:
|
||||
|
||||
unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor);
|
||||
|
||||
void EmitARMFnStart();
|
||||
void EmitARMFnEnd();
|
||||
void EmitARMExIdxCode(int Offset, const char *Blob);
|
||||
void EmitARMExIdxLsda(const char *Blob);
|
||||
|
||||
private:
|
||||
void EmitLabelDiff(const MCSymbol *From, const MCSymbol *To,
|
||||
unsigned int Size = 4);
|
||||
@@ -155,7 +167,7 @@ private:
|
||||
|
||||
// When object writer is created/initialized successfully, it is returned.
|
||||
// Or null object is returned. Client should check this.
|
||||
extern "C" ObjectWriter *InitObjWriter(const char *ObjectFilePath) {
|
||||
DLL_EXPORT ObjectWriter *InitObjWriter(const char *ObjectFilePath) {
|
||||
ObjectWriter *OW = new ObjectWriter();
|
||||
if (OW->Init(ObjectFilePath)) {
|
||||
return OW;
|
||||
@@ -164,20 +176,20 @@ extern "C" ObjectWriter *InitObjWriter(const char *ObjectFilePath) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" void FinishObjWriter(ObjectWriter *OW) {
|
||||
DLL_EXPORT void FinishObjWriter(ObjectWriter *OW) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->Finish();
|
||||
delete OW;
|
||||
}
|
||||
|
||||
extern "C" void SwitchSection(ObjectWriter *OW, const char *SectionName,
|
||||
DLL_EXPORT void SwitchSection(ObjectWriter *OW, const char *SectionName,
|
||||
CustomSectionAttributes attributes,
|
||||
const char *ComdatName) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->SwitchSection(SectionName, attributes, ComdatName);
|
||||
}
|
||||
|
||||
extern "C" void SetCodeSectionAttribute(ObjectWriter *OW,
|
||||
DLL_EXPORT void SetCodeSectionAttribute(ObjectWriter *OW,
|
||||
const char *SectionName,
|
||||
CustomSectionAttributes attributes,
|
||||
const char *ComdatName) {
|
||||
@@ -185,80 +197,80 @@ extern "C" void SetCodeSectionAttribute(ObjectWriter *OW,
|
||||
OW->SetCodeSectionAttribute(SectionName, attributes, ComdatName);
|
||||
}
|
||||
|
||||
extern "C" void EmitAlignment(ObjectWriter *OW, int ByteAlignment) {
|
||||
DLL_EXPORT void EmitAlignment(ObjectWriter *OW, int ByteAlignment) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitAlignment(ByteAlignment);
|
||||
}
|
||||
|
||||
extern "C" void EmitBlob(ObjectWriter *OW, int BlobSize, const char *Blob) {
|
||||
DLL_EXPORT void EmitBlob(ObjectWriter *OW, int BlobSize, const char *Blob) {
|
||||
assert(OW && "ObjWriter null");
|
||||
OW->EmitBlob(BlobSize, Blob);
|
||||
}
|
||||
|
||||
extern "C" void EmitIntValue(ObjectWriter *OW, uint64_t Value, unsigned Size) {
|
||||
DLL_EXPORT void EmitIntValue(ObjectWriter *OW, uint64_t Value, unsigned Size) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitIntValue(Value, Size);
|
||||
}
|
||||
|
||||
extern "C" void EmitSymbolDef(ObjectWriter *OW, const char *SymbolName) {
|
||||
DLL_EXPORT void EmitSymbolDef(ObjectWriter *OW, const char *SymbolName) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitSymbolDef(SymbolName);
|
||||
}
|
||||
|
||||
extern "C" int EmitSymbolRef(ObjectWriter *OW, const char *SymbolName,
|
||||
DLL_EXPORT int EmitSymbolRef(ObjectWriter *OW, const char *SymbolName,
|
||||
RelocType RelocType, int Delta) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->EmitSymbolRef(SymbolName, RelocType, Delta);
|
||||
}
|
||||
|
||||
extern "C" void EmitWinFrameInfo(ObjectWriter *OW, const char *FunctionName,
|
||||
DLL_EXPORT void EmitWinFrameInfo(ObjectWriter *OW, const char *FunctionName,
|
||||
int StartOffset, int EndOffset,
|
||||
const char *BlobSymbolName) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitWinFrameInfo(FunctionName, StartOffset, EndOffset, BlobSymbolName);
|
||||
}
|
||||
|
||||
extern "C" void EmitCFIStart(ObjectWriter *OW, int Offset) {
|
||||
DLL_EXPORT void EmitCFIStart(ObjectWriter *OW, int Offset) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitCFIStart(Offset);
|
||||
}
|
||||
|
||||
extern "C" void EmitCFIEnd(ObjectWriter *OW, int Offset) {
|
||||
DLL_EXPORT void EmitCFIEnd(ObjectWriter *OW, int Offset) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitCFIEnd(Offset);
|
||||
}
|
||||
|
||||
extern "C" void EmitCFILsda(ObjectWriter *OW, const char *LsdaBlobSymbolName) {
|
||||
DLL_EXPORT void EmitCFILsda(ObjectWriter *OW, const char *LsdaBlobSymbolName) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitCFILsda(LsdaBlobSymbolName);
|
||||
}
|
||||
|
||||
extern "C" void EmitCFICode(ObjectWriter *OW, int Offset, const char *Blob) {
|
||||
DLL_EXPORT void EmitCFICode(ObjectWriter *OW, int Offset, const char *Blob) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitCFICode(Offset, Blob);
|
||||
}
|
||||
|
||||
extern "C" void EmitDebugFileInfo(ObjectWriter *OW, int FileId,
|
||||
DLL_EXPORT void EmitDebugFileInfo(ObjectWriter *OW, int FileId,
|
||||
const char *FileName) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitDebugFileInfo(FileId, FileName);
|
||||
}
|
||||
|
||||
extern "C" void EmitDebugFunctionInfo(ObjectWriter *OW,
|
||||
DLL_EXPORT void EmitDebugFunctionInfo(ObjectWriter *OW,
|
||||
const char *FunctionName,
|
||||
int FunctionSize) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitDebugFunctionInfo(FunctionName, FunctionSize);
|
||||
}
|
||||
|
||||
extern "C" void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
|
||||
DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
|
||||
bool IsParam, int RangeCount,
|
||||
ICorDebugInfo::NativeVarInfo *Ranges) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitDebugVar(Name, TypeIndex, IsParam, RangeCount, Ranges);
|
||||
}
|
||||
|
||||
extern "C" void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId,
|
||||
DLL_EXPORT void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId,
|
||||
int LineNumber, int ColNumber) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitDebugLoc(NativeOffset, FileId, LineNumber, ColNumber);
|
||||
@@ -266,25 +278,25 @@ extern "C" void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId,
|
||||
|
||||
// This should be invoked at the end of module emission to finalize
|
||||
// debug module info.
|
||||
extern "C" void EmitDebugModuleInfo(ObjectWriter *OW) {
|
||||
DLL_EXPORT void EmitDebugModuleInfo(ObjectWriter *OW) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
OW->EmitDebugModuleInfo();
|
||||
}
|
||||
|
||||
extern "C" unsigned GetEnumTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetEnumTypeIndex(ObjectWriter *OW,
|
||||
EnumTypeDescriptor TypeDescriptor,
|
||||
EnumRecordTypeDescriptor *TypeRecords) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetEnumTypeIndex(TypeDescriptor, TypeRecords);
|
||||
}
|
||||
|
||||
extern "C" unsigned GetClassTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetClassTypeIndex(ObjectWriter *OW,
|
||||
ClassTypeDescriptor ClassDescriptor) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetClassTypeIndex(ClassDescriptor);
|
||||
}
|
||||
|
||||
extern "C" unsigned
|
||||
DLL_EXPORT unsigned
|
||||
GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor,
|
||||
ClassFieldsTypeDescriptior ClassFieldsDescriptor,
|
||||
DataFieldDescriptor *FieldsDescriptors) {
|
||||
@@ -293,28 +305,48 @@ GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor,
|
||||
FieldsDescriptors);
|
||||
}
|
||||
|
||||
extern "C" unsigned GetArrayTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetArrayTypeIndex(ObjectWriter *OW,
|
||||
ClassTypeDescriptor ClassDescriptor,
|
||||
ArrayTypeDescriptor ArrayDescriptor) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor);
|
||||
}
|
||||
|
||||
extern "C" unsigned GetPointerTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetPointerTypeIndex(ObjectWriter *OW,
|
||||
PointerTypeDescriptor PointerDescriptor) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetPointerTypeIndex(PointerDescriptor);
|
||||
}
|
||||
|
||||
extern "C" unsigned GetMemberFunctionTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetMemberFunctionTypeIndex(ObjectWriter *OW,
|
||||
MemberFunctionTypeDescriptor MemberDescriptor,
|
||||
uint32_t *ArgumentTypes) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes);
|
||||
}
|
||||
|
||||
extern "C" unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW,
|
||||
DLL_EXPORT unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW,
|
||||
MemberFunctionIdTypeDescriptor MemberIdDescriptor) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->GetMemberFunctionId(MemberIdDescriptor);
|
||||
}
|
||||
|
||||
DLL_EXPORT void EmitARMFnStart(ObjectWriter *OW) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->EmitARMFnStart();
|
||||
}
|
||||
|
||||
DLL_EXPORT void EmitARMFnEnd(ObjectWriter *OW) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->EmitARMFnEnd();
|
||||
}
|
||||
|
||||
DLL_EXPORT void EmitARMExIdxLsda(ObjectWriter *OW, const char *Blob) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->EmitARMExIdxLsda(Blob);
|
||||
}
|
||||
|
||||
DLL_EXPORT void EmitARMExIdxCode(ObjectWriter *OW, int Offset, const char *Blob) {
|
||||
assert(OW && "ObjWriter is null");
|
||||
return OW->EmitARMExIdxCode(Offset, Blob);
|
||||
}
|
||||
|
||||
@@ -50,8 +50,11 @@ ASM_OFFSET( 2c, 40, Thread, m_pTransitionFrame)
|
||||
ASM_OFFSET( 30, 48, Thread, m_pHackPInvokeTunnel)
|
||||
ASM_OFFSET( 40, 68, Thread, m_ppvHijackedReturnAddressLocation)
|
||||
ASM_OFFSET( 44, 70, Thread, m_pvHijackedReturnAddress)
|
||||
ASM_OFFSET( 48, 78, Thread, m_pExInfoStackHead)
|
||||
ASM_OFFSET( 4c, 80, Thread, m_threadAbortException)
|
||||
#ifdef BIT64
|
||||
ASM_OFFSET( 0, 78, Thread, m_uHijackedReturnValueFlags)
|
||||
#endif
|
||||
ASM_OFFSET( 48, 80, Thread, m_pExInfoStackHead)
|
||||
ASM_OFFSET( 4c, 88, Thread, m_threadAbortException)
|
||||
|
||||
ASM_SIZEOF( 14, 20, EHEnum)
|
||||
|
||||
|
||||
@@ -44,3 +44,7 @@ class AsmOffsets
|
||||
#include "AsmOffsets.h"
|
||||
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
namespace { char WorkaroundLNK4221Warning; };
|
||||
#endif
|
||||
|
||||
@@ -510,7 +510,7 @@ COOP_PINVOKE_HELPER(PTR_Code, RhpUpdateDispatchCellCache, (InterfaceDispatchCell
|
||||
|
||||
// Publish the new cache by atomically updating both the cache and stub pointers in the indirection
|
||||
// cell. This returns us a cache to discard which may be NULL (no previous cache), the previous cache
|
||||
// value or the cache we just allocated (another thread peformed an update first).
|
||||
// value or the cache we just allocated (another thread performed an update first).
|
||||
InterfaceDispatchCache * pDiscardedCache = UpdateCellStubAndCache(pCell, pStub, newCacheValue);
|
||||
if (pDiscardedCache)
|
||||
DiscardCache(pDiscardedCache);
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
#include "common.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "DebugFuncEval.h"
|
||||
#include "rhassert.h"
|
||||
#include "RWLock.h"
|
||||
#include "slist.h"
|
||||
#include "RuntimeInstance.h"
|
||||
|
||||
GVAL_IMPL_INIT(UInt32, g_FuncEvalMode, 0);
|
||||
GVAL_IMPL_INIT(UInt32, g_FuncEvalParameterBufferSize, 0);
|
||||
GVAL_IMPL_INIT(UInt64, g_MostRecentFuncEvalHijackInstructionPointer, 0);
|
||||
GPTR_IMPL_INIT(PTR_VOID, g_HighLevelDebugFuncEvalAbortHelperAddr, 0);
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
@@ -28,16 +31,6 @@ GPTR_IMPL_INIT(PTR_VOID, g_HighLevelDebugFuncEvalAbortHelperAddr, 0);
|
||||
return g_MostRecentFuncEvalHijackInstructionPointer;
|
||||
}
|
||||
|
||||
/* static */ HighLevelDebugFuncEvalAbortHelperType DebugFuncEval::GetHighLevelDebugFuncEvalAbortHelper()
|
||||
{
|
||||
return (HighLevelDebugFuncEvalAbortHelperType)g_HighLevelDebugFuncEvalAbortHelperAddr;
|
||||
}
|
||||
|
||||
/* static */ void DebugFuncEval::SetHighLevelDebugFuncEvalAbortHelper(HighLevelDebugFuncEvalAbortHelperType highLevelDebugFuncEvalAbortHelper)
|
||||
{
|
||||
g_HighLevelDebugFuncEvalAbortHelperAddr = (PTR_PTR_VOID)highLevelDebugFuncEvalAbortHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the global FuncEval parameter buffer size.
|
||||
/// </summary>
|
||||
@@ -73,22 +66,12 @@ EXTERN_C REDHAWK_API UInt32 __cdecl RhpGetFuncEvalMode()
|
||||
/// <remarks>
|
||||
/// This is the entry point of FuncEval abort
|
||||
/// When the debugger decides to abort the FuncEval, it will create a remote thread calling this function.
|
||||
/// This function will call back into the highLevelDebugFuncEvalAbortHelper to perform the abort.
|
||||
/// This function will call back into the DebugFuncEvalAbortHelper to perform the abort.
|
||||
EXTERN_C REDHAWK_API void __cdecl RhpInitiateFuncEvalAbort(void* pointerFromDebugger)
|
||||
{
|
||||
HighLevelDebugFuncEvalAbortHelperType highLevelDebugFuncEvalAbortHelper = DebugFuncEval::GetHighLevelDebugFuncEvalAbortHelper();
|
||||
highLevelDebugFuncEvalAbortHelper((UInt64)pointerFromDebugger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the high level debug func eval abort helper
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The high level debug func eval abort helper is a function that perform the actual func eval abort
|
||||
/// It is implemented in System.Private.Debug.dll
|
||||
EXTERN_C REDHAWK_API void __cdecl RhpSetHighLevelDebugFuncEvalAbortHelper(HighLevelDebugFuncEvalAbortHelperType highLevelDebugFuncEvalAbortHelper)
|
||||
{
|
||||
DebugFuncEval::SetHighLevelDebugFuncEvalAbortHelper(highLevelDebugFuncEvalAbortHelper);
|
||||
DebugFuncEvalAbortHelperFunctionType debugFuncEvalAbortHelperFunction = (DebugFuncEvalAbortHelperFunctionType)GetRuntimeInstance()->GetClasslibFunctionFromCodeAddress((void*)g_MostRecentFuncEvalHijackInstructionPointer, ClasslibFunctionId::DebugFuncEvalAbortHelper);
|
||||
ASSERT(debugFuncEvalAbortHelperFunction != nullptr);
|
||||
debugFuncEvalAbortHelperFunction((Int64)pointerFromDebugger);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -103,4 +86,4 @@ UInt64 DebugFuncEval::GetMostRecentFuncEvalHijackInstructionPointer()
|
||||
EXTERN_C void * RhpDebugFuncEvalHelper;
|
||||
GPTR_IMPL_INIT(PTR_VOID, g_RhpDebugFuncEvalHelperAddr, &RhpDebugFuncEvalHelper);
|
||||
|
||||
GPTR_IMPL_INIT(PTR_VOID, g_RhpInitiateFuncEvalAbortAddr, (void**)&RhpInitiateFuncEvalAbort);
|
||||
GPTR_IMPL_INIT(PTR_VOID, g_RhpInitiateFuncEvalAbortAddr, (void**)&RhpInitiateFuncEvalAbort);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
typedef void(*HighLevelDebugFuncEvalAbortHelperType)(UInt64);
|
||||
typedef void(*DebugFuncEvalAbortHelperFunctionType)(UInt64);
|
||||
|
||||
class DebugFuncEval
|
||||
{
|
||||
@@ -51,18 +51,6 @@ public:
|
||||
/// It is used for the stack walker to understand the hijack frame
|
||||
/// </remarks>
|
||||
static UInt64 GetMostRecentFuncEvalHijackInstructionPointer();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the high level debug func eval abort helper
|
||||
/// </summary>
|
||||
static HighLevelDebugFuncEvalAbortHelperType GetHighLevelDebugFuncEvalAbortHelper();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the high level debug func eval abort helper
|
||||
/// </summary>
|
||||
static void SetHighLevelDebugFuncEvalAbortHelper(HighLevelDebugFuncEvalAbortHelperType highLevelDebugFuncEvalAbortHelper);
|
||||
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
52
external/corert/src/Native/Runtime/EHHelpers.cpp
vendored
52
external/corert/src/Native/Runtime/EHHelpers.cpp
vendored
@@ -28,29 +28,6 @@
|
||||
#include "rhbinder.h"
|
||||
#include "eetype.h"
|
||||
|
||||
// Find the code manager containing the given address, which might be a return address from a managed function. The
|
||||
// address may be to another managed function, or it may be to an unmanaged function. The address may also refer to
|
||||
// an EEType.
|
||||
static ICodeManager * FindCodeManagerForClasslibFunction(void * address)
|
||||
{
|
||||
RuntimeInstance * pRI = GetRuntimeInstance();
|
||||
|
||||
// Try looking up the code manager assuming the address is for code first. This is expected to be most common.
|
||||
ICodeManager * pCodeManager = pRI->FindCodeManagerByAddress(address);
|
||||
if (pCodeManager != NULL)
|
||||
return pCodeManager;
|
||||
|
||||
// Less common, we will look for the address in any of the sections of the module. This is slower, but is
|
||||
// necessary for EEType pointers and jump stubs.
|
||||
Module * pModule = pRI->FindModuleByAddress(address);
|
||||
if (pModule != NULL)
|
||||
return pModule;
|
||||
|
||||
ASSERT_MSG(!Thread::IsHijackTarget(address), "not expected to be called with hijacked return address");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhpEHEnumInitFromStackFrameIterator, (
|
||||
StackFrameIterator* pFrameIter, void ** pMethodStartAddressOut, EHEnum* pEHEnum))
|
||||
{
|
||||
@@ -70,18 +47,7 @@ COOP_PINVOKE_HELPER(Boolean, RhpEHEnumNext, (EHEnum* pEHEnum, EHClause* pEHClaus
|
||||
// found via the provided address does not have the necessary exports.
|
||||
COOP_PINVOKE_HELPER(void *, RhpGetClasslibFunctionFromCodeAddress, (void * address, ClasslibFunctionId functionId))
|
||||
{
|
||||
// Find the code manager for the given address, which is an address into some managed module. It could
|
||||
// be code, or it could be an EEType. No matter what, it's an address into a managed module in some non-Rtm
|
||||
// type system.
|
||||
ICodeManager * pCodeManager = FindCodeManagerForClasslibFunction(address);
|
||||
|
||||
// If the address isn't in a managed module then we have no classlib function.
|
||||
if (pCodeManager == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pCodeManager->GetClasslibFunction(functionId);
|
||||
return GetRuntimeInstance()->GetClasslibFunctionFromCodeAddress(address, functionId);
|
||||
}
|
||||
|
||||
// Unmanaged helper to locate one of two classlib-provided functions that the runtime needs to
|
||||
@@ -139,8 +105,7 @@ COOP_PINVOKE_HELPER(Int32, RhGetModuleFileName, (HANDLE moduleHandle, _Out_ cons
|
||||
return PalGetModuleFileName(pModuleNameOut, moduleHandle);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhpCopyContextFromExInfo,
|
||||
(void * pOSContext, Int32 cbOSContext, PAL_LIMITED_CONTEXT * pPalContext))
|
||||
COOP_PINVOKE_HELPER(void, RhpCopyContextFromExInfo, (void * pOSContext, Int32 cbOSContext, PAL_LIMITED_CONTEXT * pPalContext))
|
||||
{
|
||||
UNREFERENCED_PARAMETER(cbOSContext);
|
||||
ASSERT(cbOSContext >= sizeof(CONTEXT));
|
||||
@@ -214,9 +179,7 @@ COOP_PINVOKE_HELPER(void, RhpCopyContextFromExInfo,
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(_AMD64_) || defined(_ARM_) || defined(_X86_) || defined(_ARM64_)
|
||||
// ARM64TODO
|
||||
struct DISPATCHER_CONTEXT
|
||||
{
|
||||
UIntNative ControlPc;
|
||||
@@ -238,9 +201,9 @@ EXTERN_C void REDHAWK_CALLCONV RhpFailFastForPInvokeExceptionCoop(IntNative PInv
|
||||
Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs);
|
||||
|
||||
EXTERN_C Int32 __stdcall RhpPInvokeExceptionGuard(PEXCEPTION_RECORD pExceptionRecord,
|
||||
UIntNative EstablisherFrame,
|
||||
PCONTEXT pContextRecord,
|
||||
DISPATCHER_CONTEXT * pDispatcherContext)
|
||||
UIntNative EstablisherFrame,
|
||||
PCONTEXT pContextRecord,
|
||||
DISPATCHER_CONTEXT * pDispatcherContext)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(EstablisherFrame);
|
||||
#ifdef APP_LOCAL_RUNTIME
|
||||
@@ -268,7 +231,6 @@ EXTERN_C Int32 __stdcall RhpPInvokeExceptionGuard(PEXCEPTION_RECORD pExcep
|
||||
if (pThread->IsDoNotTriggerGcSet())
|
||||
RhFailFast();
|
||||
|
||||
|
||||
// We promote exceptions that were not converted to managed exceptions to a FailFast. However, we have to
|
||||
// be careful because we got here via OS SEH infrastructure and, therefore, don't know what GC mode we're
|
||||
// currently in. As a result, since we're calling back into managed code to handle the FailFast, we must
|
||||
@@ -423,7 +385,8 @@ static UIntNative UnwindWriteBarrierToCaller(
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
|
||||
Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative faultAddress, PAL_LIMITED_CONTEXT* palContext, UIntNative* arg0Reg, UIntNative* arg1Reg)
|
||||
Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative faultAddress,
|
||||
PAL_LIMITED_CONTEXT* palContext, UIntNative* arg0Reg, UIntNative* arg1Reg)
|
||||
{
|
||||
UIntNative faultingIP = palContext->GetIp();
|
||||
|
||||
@@ -545,5 +508,4 @@ COOP_PINVOKE_HELPER(void, RhpFallbackFailFast, ())
|
||||
RhFailFast();
|
||||
}
|
||||
|
||||
|
||||
#endif // !DACCESS_COMPILE
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
#pragma once
|
||||
|
||||
#define ICODEMANAGER_INCLUDED
|
||||
|
||||
// TODO: Debugger/DAC support (look for TODO: JIT)
|
||||
|
||||
struct REGDISPLAY;
|
||||
@@ -23,14 +25,43 @@ struct GCEnumContext
|
||||
GCEnumCallback pCallback;
|
||||
};
|
||||
|
||||
// All values but GCRK_Unknown must correspond to MethodReturnKind enumeration in gcinfo.h
|
||||
enum GCRefKind : unsigned char
|
||||
{
|
||||
GCRK_Scalar = 0x00,
|
||||
GCRK_Object = 0x01,
|
||||
GCRK_Byref = 0x02,
|
||||
GCRK_Unknown = 0xFF,
|
||||
{
|
||||
GCRK_Scalar = 0x00,
|
||||
GCRK_Object = 0x01,
|
||||
GCRK_Byref = 0x02,
|
||||
#ifdef _TARGET_ARM64_
|
||||
// Composite return kinds for value types returned in two registers (encoded with two bits per register)
|
||||
GCRK_Scalar_Obj = (GCRK_Object << 2) | GCRK_Scalar,
|
||||
GCRK_Obj_Obj = (GCRK_Object << 2) | GCRK_Object,
|
||||
GCRK_Byref_Obj = (GCRK_Object << 2) | GCRK_Byref,
|
||||
GCRK_Scalar_Byref = (GCRK_Byref << 2) | GCRK_Scalar,
|
||||
GCRK_Obj_Byref = (GCRK_Byref << 2) | GCRK_Object,
|
||||
GCRK_Byref_Byref = (GCRK_Byref << 2) | GCRK_Byref,
|
||||
|
||||
GCRK_LastValid = GCRK_Byref_Byref,
|
||||
#else // _TARGET_ARM64_
|
||||
GCRK_LastValid = GCRK_Byref,
|
||||
#endif // _TARGET_ARM64_
|
||||
GCRK_Unknown = 0xFF,
|
||||
};
|
||||
|
||||
#ifdef _TARGET_ARM64_
|
||||
// Extract individual GCRefKind components from a composite return kind
|
||||
inline GCRefKind ExtractReg0ReturnKind(GCRefKind returnKind)
|
||||
{
|
||||
ASSERT(returnKind <= GCRK_LastValid);
|
||||
return (GCRefKind)(returnKind & (GCRK_Object | GCRK_Byref));
|
||||
}
|
||||
|
||||
inline GCRefKind ExtractReg1ReturnKind(GCRefKind returnKind)
|
||||
{
|
||||
ASSERT(returnKind <= GCRK_LastValid);
|
||||
return (GCRefKind)(returnKind >> 2);
|
||||
}
|
||||
#endif // _TARGET_ARM64_
|
||||
|
||||
//
|
||||
// MethodInfo is placeholder type used to allocate space for MethodInfo. Maximum size
|
||||
// of the actual method should be less or equal to the placeholder size.
|
||||
@@ -66,9 +97,7 @@ struct EHClause
|
||||
void* m_pTargetType;
|
||||
};
|
||||
|
||||
// Constants used with RhpGetClasslibFunction, to indicate which classlib function
|
||||
// we are interested in.
|
||||
// Note: make sure you change the def in System\Runtime\exceptionhandling.cs if you change this!
|
||||
// Note: make sure you change the def in System\Runtime\InternalCalls.cs if you change this!
|
||||
enum class ClasslibFunctionId
|
||||
{
|
||||
GetRuntimeException = 0,
|
||||
@@ -78,6 +107,8 @@ enum class ClasslibFunctionId
|
||||
CheckStaticClassConstruction = 4,
|
||||
GetSystemArrayEEType = 5,
|
||||
OnFirstChanceException = 6,
|
||||
DebugFuncEvalHelper = 7,
|
||||
DebugFuncEvalAbortHelper = 8,
|
||||
};
|
||||
|
||||
enum class AssociatedDataFlags : unsigned char
|
||||
|
||||
@@ -553,9 +553,19 @@ COOP_PINVOKE_HELPER(UInt8 *, RhGetCodeTarget, (UInt8 * pCodeOrg))
|
||||
pCode++;
|
||||
}
|
||||
// is this an indirect jump?
|
||||
if (/* ARM64TODO */ false)
|
||||
// adrp xip0,#imm21; ldr xip0,[xip0,#imm12]; br xip0
|
||||
if ((pCode[0] & 0x9f00001f) == 0x90000010 &&
|
||||
(pCode[1] & 0xffc003ff) == 0xf9400210 &&
|
||||
pCode[2] == 0xd61f0200)
|
||||
{
|
||||
// ARM64TODO
|
||||
// normal import stub - dist to IAT cell is relative to (PC & ~0xfff)
|
||||
// adrp: imm = SignExtend(immhi:immlo:Zeros(12), 64);
|
||||
Int64 distToIatCell = (((((Int64)pCode[0] & ~0x1f) << 40) >> 31) | ((pCode[0] >> 17) & 0x3000));
|
||||
// ldr: offset = LSL(ZeroExtend(imm12, 64), 3);
|
||||
distToIatCell += (pCode[1] >> 7) & 0x7ff8;
|
||||
UInt8 ** pIatCell = (UInt8 **)(((Int64)pCode & ~0xfff) + distToIatCell);
|
||||
ASSERT(pModule == NULL || pModule->ContainsDataAddress(pIatCell));
|
||||
return *pIatCell;
|
||||
}
|
||||
// is this an unboxing stub followed by a relative jump?
|
||||
else if (unboxingStub && (pCode[0] >> 26) == 0x5)
|
||||
@@ -697,7 +707,7 @@ COOP_PINVOKE_HELPER(Boolean, RhpArrayCopy, (Array * pSourceArray, Int32 sourceIn
|
||||
|
||||
//
|
||||
// This function handles all cases of Array.Clear that do not require conversions. It returns false if the operation cannot be performed, leaving
|
||||
// the handling of the complex cases or throwing apppropriate exception to the higher level framework. It is only allowed to return false for illegal
|
||||
// the handling of the complex cases or throwing appropriate exception to the higher level framework. It is only allowed to return false for illegal
|
||||
// calls as the BCL side has fallback for "complex cases" only.
|
||||
//
|
||||
COOP_PINVOKE_HELPER(Boolean, RhpArrayClear, (Array * pArray, Int32 index, Int32 length))
|
||||
|
||||
@@ -26,9 +26,9 @@ else()
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
# The AsmOffsets.cs is consumed later by the managed build
|
||||
# The AsmOffsetsPortable.cs is consumed later by the managed build
|
||||
TARGET PortableRuntime
|
||||
COMMAND ${CMAKE_CXX_COMPILER} ${COMPILER_LANGUAGE} ${DEFINITIONS} ${PREPROCESSOR_FLAGS} -I"${ARCH_SOURCES_DIR}" "${ASM_OFFSETS_CSPP}" >"${CMAKE_CURRENT_BINARY_DIR}/AsmOffsets.cs"
|
||||
COMMAND ${CMAKE_CXX_COMPILER} ${COMPILER_LANGUAGE} ${DEFINITIONS} ${PREPROCESSOR_FLAGS} -I"${ARCH_SOURCES_DIR}" "${ASM_OFFSETS_CSPP}" >"${CMAKE_CURRENT_BINARY_DIR}/AsmOffsetsPortable.cs"
|
||||
DEPENDS "${RUNTIME_DIR}/AsmOffsets.cpp" "${RUNTIME_DIR}/AsmOffsets.h"
|
||||
)
|
||||
|
||||
|
||||
110
external/corert/src/Native/Runtime/RHCodeMan.cpp
vendored
110
external/corert/src/Native/Runtime/RHCodeMan.cpp
vendored
@@ -97,7 +97,7 @@ void ReportRegisterSet(UInt8 regSet, REGDISPLAY * pContext, GCEnumContext * hCal
|
||||
{
|
||||
// 2. 00lRRRRR - normal "register set" encoding, pinned and interior attributes both false
|
||||
// a. l - this is the last descriptor
|
||||
// b. RRRRR - this is the register mask for { r4, r5, r6, r7, r8 }
|
||||
// b. RRRRR - this is the register mask for { r4-r8 }
|
||||
|
||||
if (regSet & CSR_MASK_R4) { ReportObject(hCallback, GetRegObjectAddr<CSR_NUM_R4>(pContext), 0); }
|
||||
if (regSet & CSR_MASK_R5) { ReportObject(hCallback, GetRegObjectAddr<CSR_NUM_R5>(pContext), 0); }
|
||||
@@ -373,9 +373,10 @@ void ReportLocalSlots(UInt8 localsEnc, REGDISPLAY * pContext, GCEnumContext * hC
|
||||
{
|
||||
// 4. 10l1SSSS - "local stack slot set" encoding, pinned and interior attributes both false
|
||||
// a. l - last descriptor
|
||||
// b. SSSS - set of "local slots" #0 - #3 - local slot 0 is at offset -8 from the last pushed
|
||||
// callee saved register, local slot 1 is at offset - 16, etc - in other words, these are the
|
||||
// slots normally used for locals
|
||||
// b. SSSS - set of "local slots" #0-#3 - local slot #0 is at offset -POINTER_SIZE from
|
||||
// the last pushed callee saved register, local slot #1 is at offset -2*POINTER_SIZE,
|
||||
// etc - in other words, these are the slots normally used for locals. The non-sensical
|
||||
// encoding with SSSS = 0000 is reserved for the "common vars" case 8 below.
|
||||
if (localsEnc & 0x01) { ReportLocalSlot(0, pContext, hCallback, pHeader); }
|
||||
if (localsEnc & 0x02) { ReportLocalSlot(1, pContext, hCallback, pHeader); }
|
||||
if (localsEnc & 0x04) { ReportLocalSlot(2, pContext, hCallback, pHeader); }
|
||||
@@ -385,7 +386,7 @@ void ReportLocalSlots(UInt8 localsEnc, REGDISPLAY * pContext, GCEnumContext * hC
|
||||
{
|
||||
// 5. 10l0ssss - "local slot" encoding, pinned and interior attributes are both false
|
||||
// a. l - last descriptor
|
||||
// b. ssss - "local slot" #4 - #19
|
||||
// b. ssss - "local slot" #4-#19 (#0-#3 are encoded by case 4 above)
|
||||
UInt32 localNum = (localsEnc & 0xF) + 4;
|
||||
ReportLocalSlot(localNum, pContext, hCallback, pHeader);
|
||||
}
|
||||
@@ -401,10 +402,10 @@ void ReportStackSlots(UInt8 firstEncByte, REGDISPLAY * pContext, GCEnumContext *
|
||||
// e. s - offset sign
|
||||
// f. m - mask follows
|
||||
// g. offset - variable length unsigned integer
|
||||
// h. mask - variable length unsigned integer (only present if m-bit is 1) - this can describe
|
||||
// multiple stack locations with the same attributes. E.g., if you want to describe stack
|
||||
// locations 0x20, 0x28, 0x38, you would give a (starting) offset of 0x20 and a mask of
|
||||
// 000000101 = 0x05. Up to 33 stack locations can be described.
|
||||
// h. mask - variable length unsigned integer (only present if m-bit is 1) - describes multiple
|
||||
// (up to 33) stack locations having the same attributes. E.g., to describe stack locations
|
||||
// 0x20, 0x28, 0x38, you specify the starting offset 0x20 and the mask 000000101 = 0x5.
|
||||
// The mask describes the next 32 stack locations after the first one.
|
||||
|
||||
UInt32 flags = 0;
|
||||
if (firstEncByte & 0x08) { flags |= GC_CALL_PINNED; }
|
||||
@@ -478,7 +479,7 @@ void ReportScratchRegs(UInt8 firstEncByte, REGDISPLAY * pContext, GCEnumContext
|
||||
// e. IIIIIII - interior scratch register mask for { rax, rcx, rdx, r8, r9, r10, r11 } iff 'i' is 1
|
||||
// f. PPPPPPP - pinned scratch register mask for { rax, rcx, rdx, r8, r9, r10, r11 } iff 'p' is 1
|
||||
//
|
||||
// For ARM64 the scheme above is extended to support the bigger register set:
|
||||
// For ARM64 the scheme above is extended to support the larger register set:
|
||||
// - 11lip010 0RRRRRRR [0IIIIIII] [0PPPPPPP] for { x0-x6 }
|
||||
// - 11lip010 1RRRRRRR 0RRRRRRR [[1IIIIIII] 0IIIIIII] [[1PPPPPPP] 0PPPPPPP] for { x0-x13 }
|
||||
// - 11lip010 1RRRRRRR 1RRRRRRR 000RRRRR [0*2(1IIIIIII) 000IIIII] [0*2(1PPPPPPP) 000PPPPP] for { x0-x15, xip0, xip1, lr }
|
||||
@@ -505,7 +506,7 @@ void ReportScratchRegs(UInt8 firstEncByte, REGDISPLAY * pContext, GCEnumContext
|
||||
}
|
||||
|
||||
// Enumerate all live object references in that function using the virtual register set. Same reference
|
||||
// location cannot be enumerated multiple times (but all differenct references pointing to the same object
|
||||
// location cannot be enumerated multiple times (but all different references pointing to the same object
|
||||
// have to be individually enumerated).
|
||||
// Returns success of operation.
|
||||
void EECodeManager::EnumGcRefs(MethodGcInfoPointers * pMethodInfo,
|
||||
@@ -632,7 +633,7 @@ ContinueUnconditionally:
|
||||
// a. l - this is the last descriptor
|
||||
// b. RRRRR - this is the register mask for { rbx, rsi, rdi, rbp, r12 }, ARM = { r4-r8 }
|
||||
//
|
||||
// For ARM64 the scheme above is extended to support the bigger register set:
|
||||
// For ARM64 the scheme above is extended to support the larger register set:
|
||||
// 00lvRRRR [RRRRRRRR] - normal "register set" encoding, pinned and interior attributes both false
|
||||
// a. l - this is the last descriptor
|
||||
// b. v - extra byte follows
|
||||
@@ -648,14 +649,14 @@ ContinueUnconditionally:
|
||||
//
|
||||
// 4. 10l1SSSS - "local stack slot set" encoding, pinned and interior attributes both false
|
||||
// a. l - last descriptor
|
||||
// b. SSSS - set of "local slots" #0 - #3 - local slot 0 is at offset -8 from the last pushed
|
||||
// callee saved register, local slot 1 is at offset - 16, etc - in other words, these are the
|
||||
// slots normally used for locals. The non-sensical encoding with SSSS = 0000 is reserved for
|
||||
// the "common vars" case under 8 below.
|
||||
// b. SSSS - set of "local slots" #0-#3 - local slot #0 is at offset -POINTER_SIZE from
|
||||
// the last pushed callee saved register, local slot #1 is at offset -2*POINTER_SIZE,
|
||||
// etc - in other words, these are the slots normally used for locals. The non-sensical
|
||||
// encoding with SSSS = 0000 is reserved for the "common vars" case 8 below.
|
||||
//
|
||||
// 5. 10l0ssss - "local slot" encoding
|
||||
// 5. 10l0ssss - "local slot" encoding, pinned and interior attributes are both false
|
||||
// a. l - last descriptor
|
||||
// b. ssss - "local slot" #4 - #19
|
||||
// b. ssss - "local slot" #4-#19 (#0-#3 are encoded by case 4 above)
|
||||
//
|
||||
// 6. 11lipfsm {offset} [mask] - [multiple] stack slot encoding
|
||||
// a. l - last descriptor
|
||||
@@ -665,10 +666,10 @@ ContinueUnconditionally:
|
||||
// e. s - offset sign
|
||||
// f. m - mask follows
|
||||
// g. offset - variable length unsigned integer
|
||||
// h. mask - variable length unsigned integer (only present if m-bit is 1) - this can describe
|
||||
// multiple stack locations with the same attributes. E.g., if you want to describe stack
|
||||
// locations 0x20, 0x28, 0x38, you would give a (starting) offset of 0x20 and a mask of
|
||||
// 000000101 = 0x05. Up to 33 stack locations can be described.
|
||||
// h. mask - variable length unsigned integer (only present if m-bit is 1) - describes multiple
|
||||
// (up to 33) stack locations having the same attributes. E.g., to describe stack locations
|
||||
// 0x20, 0x28, 0x38, you specify the starting offset 0x20 and the mask 000000101 = 0x5.
|
||||
// The mask describes the next 32 stack locations after the first one.
|
||||
//
|
||||
// 7. 11lip010 0RRRRRRR [0IIIIIII] [0PPPPPPP] - live scratch reg reporting, this uses the SP-xxx encoding
|
||||
// from #6 since we cannot have stack locations at negative
|
||||
@@ -680,7 +681,7 @@ ContinueUnconditionally:
|
||||
// e. IIIIIII - interior scratch register mask for { rax, rcx, rdx, r8, r9, r10, r11 } iff 'i' is 1
|
||||
// f. PPPPPPP - pinned scratch register mask for { rax, rcx, rdx, r8, r9, r10, r11 } iff 'p' is 1
|
||||
//
|
||||
// For ARM64 the scheme above is extended to support the bigger register set:
|
||||
// For ARM64 the scheme above is extended to support the larger register set:
|
||||
// - 11lip010 0RRRRRRR [0IIIIIII] [0PPPPPPP] for { x0-x6 }
|
||||
// - 11lip010 1RRRRRRR 0RRRRRRR [[1IIIIIII] 0IIIIIII] [[1PPPPPPP] 0PPPPPPP] for { x0-x13 }
|
||||
// - 11lip010 1RRRRRRR 1RRRRRRR 000RRRRR [0*2(1IIIIIII) 000IIIII] [0*2(1PPPPPPP) 000PPPPP] for { x0-x15, xip0, xip1, lr }
|
||||
@@ -792,7 +793,7 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
REGDISPLAY * pContext)
|
||||
{
|
||||
// We could implement this unwind if we wanted, but there really isn't any reason
|
||||
ASSERT(pInfoHeader->GetReturnKind() != GCInfoHeader::MRK_ReturnsToNative);
|
||||
ASSERT(!pInfoHeader->ReturnsToNative());
|
||||
|
||||
bool ebpFrame = pInfoHeader->HasFramePointer();
|
||||
|
||||
@@ -988,12 +989,14 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
}
|
||||
|
||||
PTR_UIntNative RSP = (PTR_UIntNative)rawRSP;
|
||||
bool restoredIP = false;
|
||||
|
||||
if (ebpFrame)
|
||||
{
|
||||
pContext->pFP = RSP++;
|
||||
pContext->SetAddrOfIP((PTR_PCODE)RSP); // save off the return address location
|
||||
pContext->SetIP(*RSP++); // pop the return address
|
||||
restoredIP = true;
|
||||
}
|
||||
|
||||
if (!pInfoHeader->AreFPLROnTop())
|
||||
@@ -1002,6 +1005,8 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
ASSERT(!pInfoHeader->HasGSCookie());
|
||||
}
|
||||
|
||||
ASSERT_MSG(pInfoHeader->IsFunclet() || !(dac_cast<TADDR>(RSP) & 0xf), "Callee save area must be 16-byte aligned");
|
||||
|
||||
if (saveSize > 0)
|
||||
{
|
||||
CalleeSavedRegMask regMask = pInfoHeader->GetSavedRegs();
|
||||
@@ -1010,6 +1015,7 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
ASSERT_MSG(!ebpFrame, "Chained frame cannot have CSR_MASK_LR mask set");
|
||||
pContext->SetAddrOfIP((PTR_PCODE)RSP); // save off the return address location
|
||||
pContext->SetIP(*RSP++); // pop the return address
|
||||
restoredIP = true;
|
||||
}
|
||||
if (regMask & CSR_MASK_X19) { pContext->pX19 = RSP++; }
|
||||
if (regMask & CSR_MASK_X20) { pContext->pX20 = RSP++; }
|
||||
@@ -1024,6 +1030,12 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
if (regMask & CSR_MASK_FP ) { ASSERT(!ebpFrame); pContext->pFP = RSP++; }
|
||||
}
|
||||
|
||||
if (!restoredIP)
|
||||
{
|
||||
pContext->SetAddrOfIP((PTR_PCODE)pContext->pLR);
|
||||
pContext->SetIP(*pContext->pLR);
|
||||
}
|
||||
|
||||
UInt8 vfpRegMask = (UInt8)pInfoHeader->GetVfpRegsPushedMask();
|
||||
if (vfpRegMask)
|
||||
{
|
||||
@@ -1048,6 +1060,10 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
|
||||
RSP += pInfoHeader->ParmRegsPushedCount();
|
||||
|
||||
// Excluding funclets, the total size of the callee save area and the param home area is always a multiple of 16.
|
||||
// The compiler enforces that by placing an 8-byte padding between those areas if needed.
|
||||
// Account for that padding and ensure that the unwound SP is 16-byte aligned.
|
||||
RSP = dac_cast<PTR_UIntNative>((dac_cast<TADDR>(RSP) + 0xf) & ~0xf);
|
||||
#else
|
||||
|
||||
#error NYI - For this arch
|
||||
@@ -1060,7 +1076,7 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
|
||||
|
||||
PTR_VOID EECodeManager::GetReversePInvokeSaveFrame(GCInfoHeader * pHeader, REGDISPLAY * pContext)
|
||||
{
|
||||
if (pHeader->GetReturnKind() != GCInfoHeader::MRK_ReturnsToNative)
|
||||
if (!pHeader->ReturnsToNative())
|
||||
return NULL;
|
||||
|
||||
Int32 frameOffset = pHeader->GetReversePinvokeFrameOffset();
|
||||
@@ -1078,7 +1094,7 @@ UIntNative EECodeManager::GetConservativeUpperBoundForOutgoingArgs(GCInfoHeader
|
||||
{
|
||||
UIntNative upperBound;
|
||||
|
||||
if (pInfoHeader->GetReturnKind() == GCInfoHeader::MRK_ReturnsToNative)
|
||||
if (pInfoHeader->ReturnsToNative())
|
||||
{
|
||||
// Reverse PInvoke case. The embedded reverse PInvoke frame is guaranteed to reside above
|
||||
// all outgoing arguments.
|
||||
@@ -1098,7 +1114,9 @@ UIntNative EECodeManager::GetConservativeUpperBoundForOutgoingArgs(GCInfoHeader
|
||||
|
||||
#elif defined(_TARGET_ARM64_)
|
||||
|
||||
PORTABILITY_ASSERT("@TODO: FIXME:ARM64");
|
||||
// ARM64 frame pointer case. The pushed FP value is guaranteed to reside above
|
||||
// all outgoing arguments.
|
||||
upperBound = pContext->GetFP();
|
||||
|
||||
#elif defined(_TARGET_X86_)
|
||||
|
||||
@@ -1169,7 +1187,7 @@ PTR_PTR_VOID EECodeManager::GetReturnAddressLocationForHijack(
|
||||
|
||||
// We *could* hijack a reverse-pinvoke method, but it doesn't get us much because we already synchronize
|
||||
// with the GC on the way back to native code.
|
||||
if (pHeader->GetReturnKind() == GCInfoHeader::MRK_ReturnsToNative)
|
||||
if (pHeader->ReturnsToNative())
|
||||
return NULL;
|
||||
|
||||
if (pHeader->IsFunclet())
|
||||
@@ -1273,21 +1291,18 @@ GCRefKind EECodeManager::GetReturnValueKind(GCInfoHeader * pInfoHeader)
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_ReturnsScalar == GCRK_Scalar, "GCInfoHeader::MRK_ReturnsScalar does not match GCRK_Scalar");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_ReturnsObject == GCRK_Object, "GCInfoHeader::MRK_ReturnsObject does not match GCRK_Object");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_ReturnsByref == GCRK_Byref, "GCInfoHeader::MRK_ReturnsByref does not match GCRK_Byref");
|
||||
#ifdef _TARGET_ARM64_
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Scalar_Obj == GCRK_Scalar_Obj, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Obj_Obj == GCRK_Obj_Obj, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Byref_Obj == GCRK_Byref_Obj, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Scalar_Byref == GCRK_Scalar_Byref, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Obj_Byref == GCRK_Obj_Byref, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
static_assert((GCRefKind)GCInfoHeader::MRK_Byref_Byref == GCRK_Byref_Byref, "GCRefKind and MethodReturnKind enumerations do not match");
|
||||
#endif
|
||||
|
||||
GCInfoHeader::MethodReturnKind retKind = pInfoHeader->GetReturnKind();
|
||||
switch (retKind)
|
||||
{
|
||||
case GCInfoHeader::MRK_ReturnsScalar:
|
||||
case GCInfoHeader::MRK_ReturnsToNative:
|
||||
return GCRK_Scalar;
|
||||
case GCInfoHeader::MRK_ReturnsObject:
|
||||
return GCRK_Object;
|
||||
case GCInfoHeader::MRK_ReturnsByref:
|
||||
return GCRK_Byref;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE_MSG("unexpected return kind");
|
||||
ASSERT_MSG(retKind <= GCInfoHeader::MRK_LastValid, "unexpected return kind");
|
||||
return (retKind == GCInfoHeader::MRK_ReturnsToNative) ? GCRK_Scalar : (GCRefKind)retKind;
|
||||
}
|
||||
|
||||
bool EECodeManager::GetEpilogOffset(
|
||||
@@ -1345,7 +1360,7 @@ void ** EECodeManager::GetReturnAddressLocationFromEpilog(GCInfoHeader * pInfoHe
|
||||
|
||||
//ASSERT(VerifyEpilogBytes(pInfoHeader, (Code *)pbEpilogStart));
|
||||
// We could find the return address of a native-callable method, but it's not very useful at the moment.
|
||||
ASSERT(pInfoHeader->GetReturnKind() != GCInfoHeader::MRK_ReturnsToNative);
|
||||
ASSERT(!pInfoHeader->ReturnsToNative());
|
||||
UInt8 * pbEpilog = pbEpilogStart;
|
||||
|
||||
#ifdef _X86_
|
||||
@@ -1796,7 +1811,7 @@ inline bool IsFramelessArm64(void)
|
||||
|
||||
void CheckHijackInEpilog(GCInfoHeader * pInfoHeader, Code * pEpilog, Code * pEpilogStart, UInt32 epilogSize)
|
||||
{
|
||||
ASSERT(pInfoHeader->GetReturnKind() != GCInfoHeader::MRK_ReturnsToNative);
|
||||
ASSERT(!pInfoHeader->ReturnsToNative());
|
||||
if (IS_FRAMELESS())
|
||||
return;
|
||||
|
||||
@@ -1852,8 +1867,7 @@ bool VerifyEpilogBytesX86(GCInfoHeader * pInfoHeader, Code * pEpilogStart, UInt3
|
||||
Code * pEpilog = pEpilogStart;
|
||||
|
||||
// NativeCallable methods aren't return-address-hijacked, so we don't care about the epilog format.
|
||||
bool returnsToNative = (pInfoHeader->GetReturnKind() == GCInfoHeader::MRK_ReturnsToNative);
|
||||
if (returnsToNative)
|
||||
if (pInfoHeader->ReturnsToNative())
|
||||
return true;
|
||||
|
||||
if (pInfoHeader->HasFramePointer())
|
||||
@@ -2047,8 +2061,7 @@ bool VerifyEpilogBytesAMD64(GCInfoHeader * pInfoHeader, Code * pEpilogStart, UIn
|
||||
Code * pEpilog = pEpilogStart;
|
||||
|
||||
// NativeCallable methods aren't return-address-hijacked, so we don't care about the epilog format.
|
||||
bool returnsToNative = (pInfoHeader->GetReturnKind() == GCInfoHeader::MRK_ReturnsToNative);
|
||||
if (returnsToNative)
|
||||
if (pInfoHeader->ReturnsToNative())
|
||||
return true;
|
||||
|
||||
CHECK_HIJACK_IN_EPILOG();
|
||||
@@ -2217,8 +2230,7 @@ bool VerifyEpilogBytesARM(GCInfoHeader * pInfoHeader, Code * pEpilogStart, UInt3
|
||||
UInt16 * pEpilog = (UInt16 *)pEpilogStart;
|
||||
|
||||
// NativeCallable methods aren't return-address-hijacked, so we don't care about the epilog format.
|
||||
bool returnsToNative = (pInfoHeader->GetReturnKind() == GCInfoHeader::MRK_ReturnsToNative);
|
||||
if (returnsToNative)
|
||||
if (pInfoHeader->ReturnsToNative())
|
||||
return true;
|
||||
|
||||
CHECK_HIJACK_IN_EPILOG();
|
||||
|
||||
@@ -68,12 +68,12 @@ UInt32 RhConfig::ReadConfigValue(_In_z_ const TCHAR *wszName, UInt32 uiDefaultVa
|
||||
//reads a config value from rhconfig.ini into outputBuffer buffer returning the length of the value.
|
||||
//lazily reads the file so if the file is not yet read, it will read it on first called
|
||||
//if the file is not avaliable, or unreadable zero will always be returned
|
||||
//cchOuputBuffer is the maximum number of characters to write to outputBuffer
|
||||
//cchOutputBuffer is the maximum number of characters to write to outputBuffer
|
||||
//cchOutputBuffer must be a size >= CONFIG_VAL_MAXLEN + 1
|
||||
UInt32 RhConfig::GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOuputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOuputBuffer)
|
||||
UInt32 RhConfig::GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer)
|
||||
{
|
||||
//the buffer needs to be big enough to read the value buffer + null terminator
|
||||
if (cchOuputBuffer < CONFIG_VAL_MAXLEN + 1)
|
||||
if (cchOutputBuffer < CONFIG_VAL_MAXLEN + 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ UInt32 RhConfig::GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_
|
||||
|
||||
UInt32 iValue;
|
||||
|
||||
for (iValue = 0; (iValue < CONFIG_VAL_MAXLEN + 1) && (iValue < (Int32)cchOuputBuffer); iValue++)
|
||||
for (iValue = 0; (iValue < CONFIG_VAL_MAXLEN + 1) && (iValue < (Int32)cchOutputBuffer); iValue++)
|
||||
{
|
||||
outputBuffer[iValue] = ((ConfigPair*)g_iniSettings)[iSettings].Value[iValue];
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ private:
|
||||
//reads a config value from rhconfig.ini into outputBuffer buffer returning the length of the value.
|
||||
//lazily reads the file so if the file is not yet read, it will read it on first called
|
||||
//if the file is not avaliable, or unreadable zero will always be returned
|
||||
//cchOuputBuffer is the maximum number of characters to write to outputBuffer
|
||||
UInt32 GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOuputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOuputBuffer);
|
||||
//cchOutputBuffer is the maximum number of characters to write to outputBuffer
|
||||
UInt32 GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);
|
||||
|
||||
static bool priv_isspace(char c)
|
||||
{
|
||||
|
||||
@@ -179,6 +179,47 @@ ICodeManager * RuntimeInstance::FindCodeManagerByAddress(PTR_VOID pvAddress)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
// Find the code manager containing the given address, which might be a return address from a managed function. The
|
||||
// address may be to another managed function, or it may be to an unmanaged function. The address may also refer to
|
||||
// an EEType.
|
||||
ICodeManager * RuntimeInstance::FindCodeManagerForClasslibFunction(PTR_VOID address)
|
||||
{
|
||||
// Try looking up the code manager assuming the address is for code first. This is expected to be most common.
|
||||
ICodeManager * pCodeManager = FindCodeManagerByAddress(address);
|
||||
if (pCodeManager != NULL)
|
||||
return pCodeManager;
|
||||
|
||||
// Less common, we will look for the address in any of the sections of the module. This is slower, but is
|
||||
// necessary for EEType pointers and jump stubs.
|
||||
Module * pModule = FindModuleByAddress(address);
|
||||
if (pModule != NULL)
|
||||
return pModule;
|
||||
|
||||
ASSERT_MSG(!Thread::IsHijackTarget(address), "not expected to be called with hijacked return address");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * RuntimeInstance::GetClasslibFunctionFromCodeAddress(PTR_VOID address, ClasslibFunctionId functionId)
|
||||
{
|
||||
// Find the code manager for the given address, which is an address into some managed module. It could
|
||||
// be code, or it could be an EEType. No matter what, it's an address into a managed module in some non-Rtm
|
||||
// type system.
|
||||
ICodeManager * pCodeManager = FindCodeManagerForClasslibFunction(address);
|
||||
|
||||
// If the address isn't in a managed module then we have no classlib function.
|
||||
if (pCodeManager == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pCodeManager->GetClasslibFunction(functionId);
|
||||
}
|
||||
|
||||
#endif // DACCESS_COMPILE
|
||||
|
||||
PTR_UInt8 RuntimeInstance::GetTargetOfUnboxingAndInstantiatingStub(PTR_VOID ControlPC)
|
||||
{
|
||||
ICodeManager * pCodeManager = FindCodeManagerByAddress(ControlPC);
|
||||
@@ -576,22 +617,22 @@ void RuntimeInstance::Destroy()
|
||||
|
||||
bool RuntimeInstance::ShouldHijackLoopForGcStress(UIntNative CallsiteIP)
|
||||
{
|
||||
#if defined(FEATURE_GC_STRESS) & !defined(DACCESS_COMPILE)
|
||||
#ifdef FEATURE_GC_STRESS
|
||||
return ShouldHijackForGcStress(CallsiteIP, htLoop);
|
||||
#else // FEATURE_GC_STRESS & !DACCESS_COMPILE
|
||||
#else // FEATURE_GC_STRESS
|
||||
UNREFERENCED_PARAMETER(CallsiteIP);
|
||||
return false;
|
||||
#endif // FEATURE_GC_STRESS & !DACCESS_COMPILE
|
||||
#endif // FEATURE_GC_STRESS
|
||||
}
|
||||
|
||||
bool RuntimeInstance::ShouldHijackCallsiteForGcStress(UIntNative CallsiteIP)
|
||||
{
|
||||
#if defined(FEATURE_GC_STRESS) & !defined(DACCESS_COMPILE)
|
||||
#ifdef FEATURE_GC_STRESS
|
||||
return ShouldHijackForGcStress(CallsiteIP, htCallsite);
|
||||
#else // FEATURE_GC_STRESS & !DACCESS_COMPILE
|
||||
#else // FEATURE_GC_STRESS
|
||||
UNREFERENCED_PARAMETER(CallsiteIP);
|
||||
return false;
|
||||
#endif // FEATURE_GC_STRESS & !DACCESS_COMPILE
|
||||
#endif // FEATURE_GC_STRESS
|
||||
}
|
||||
|
||||
// This method should only be called during DllMain for modules with GcStress enabled. The locking done by
|
||||
@@ -889,7 +930,7 @@ COOP_PINVOKE_HELPER(void *, RhNewInterfaceDispatchCell, (EEType * pInterface, In
|
||||
return NULL;
|
||||
|
||||
// Due to the synchronization mechanism used to update this indirection cell we must ensure the cell's alignment is twice that of a pointer.
|
||||
// Fortunately, Windows heap guarantees this aligment.
|
||||
// Fortunately, Windows heap guarantees this alignment.
|
||||
ASSERT(IS_ALIGNED(pCell, 2 * POINTER_SIZE));
|
||||
ASSERT(IS_ALIGNED(pInterface, (InterfaceDispatchCell::IDC_CachePointerMask + 1)));
|
||||
|
||||
@@ -914,4 +955,4 @@ COOP_PINVOKE_HELPER(PTR_UInt8, RhGetThreadLocalStorageForDynamicType, (UInt32 uO
|
||||
return pCurrentThread->AllocateThreadLocalStorageForDynamicType(uOffset, tlsStorageSize, numTlsCells);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // DACCESS_COMPILE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user