Imported Upstream version 5.14.0.78

Former-commit-id: 3494343bcc9ddb42b36b82dd9ae7b69e85e0229f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-05-10 08:37:03 +00:00
parent 74b74abd9f
commit 19234507ba
1776 changed files with 67755 additions and 31107 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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 ""

View File

@@ -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;
}
}

View File

@@ -23,4 +23,8 @@ GetCompleteClassTypeIndex
GetArrayTypeIndex
GetPointerTypeIndex
GetMemberFunctionTypeIndex
GetMemberFunctionIdTypeIndex
GetMemberFunctionIdTypeIndex
EmitARMFnStart
EmitARMFnEnd
EmitARMExIdxCode
EmitARMExIdxLsda

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -44,3 +44,7 @@ class AsmOffsets
#include "AsmOffsets.h"
};
#ifdef _MSC_VER
namespace { char WorkaroundLNK4221Warning; };
#endif

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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))

View File

@@ -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"
)

View File

@@ -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();

View File

@@ -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];

View File

@@ -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)
{

View File

@@ -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