Skip to content

Commit

Permalink
Update coredistools (#96286)
Browse files Browse the repository at this point in the history
* Update coredistools

Update to the 1.2.0 version of the coredistools package.

Also, implement a basic late disassembler for RyuJIT based on
coredistools (previously, this depended on closed-source msvcdis).

Various changes:
1. Remove unused AddressMap in SPMI. Removed a bunch of cases in
the NearDiffer that were using it.
2. Change arm64 emitter unit tests to not require `verbose`
3. Always build in the late disassembler under DEBUG. It's only
used when `JitLateDisasm` is set.
4. Implement new arm32 callback mechanism for movw/movt handling
in the NearDiffer.

* Allow fallback to coredistools 1.1.0

* Fixes

* Formatting

* Fixes

1. Fix Risc-V build: only build LATE_DISASM for platforms where
coredistool support exists.
2. Defer load and initialization of coredistools.dll library for
LATE_DISASM until we actually need it.
3. For arm64, in late disasm, if there is a failure, try to recover
by skipping one 4-byte instruction.

* Be smarter about initializing and uninitializing coredistools

In particular, only load the coredistools library once, not
once per function to disassemble.

* Update to 1.4.0
  • Loading branch information
BruceForstall committed Jan 3, 2024
1 parent 867250c commit 5455432
Show file tree
Hide file tree
Showing 17 changed files with 699 additions and 319 deletions.
84 changes: 69 additions & 15 deletions src/coreclr/inc/coredistools.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

//===--------- coredistools.h - Dissassembly tools for CoreClr ------------===//
//===--------- coredistools.h - Disassembly tools for CoreClr ------------===//
//
// Core Disassembly Tools API Version 1.0.1-prerelease
// Core Disassembly Tools API Version 1.4.0
// Disassembly tools required by CoreCLR for utilities like
// GCStress and SuperPMI
// GCStress, SuperPMI, and R2RDump.
//===----------------------------------------------------------------------===//

#if !defined(_COREDISTOOLS_H_)
Expand Down Expand Up @@ -41,7 +41,8 @@ enum TargetArch {
Target_X86,
Target_X64,
Target_Thumb,
Target_Arm64
Target_Arm64,
Target_LoongArch64
};

struct CorDisasm;
Expand All @@ -60,14 +61,28 @@ struct PrintControl {
// The type of a custom function provided by the user to determine
// if two offsets are considered equivalent wrt diffing code blocks.
// Offset1 and Offset2 are the two offsets to be compared.
// BlockOffset is the offest of the instructions (that contain Offset1
// BlockOffset is the offset of the instructions (that contain Offset1
// and Offset2) from the beginning of their respective code blocks.
// InstructionLength is the length of the current instruction being
// compared for equivalency.
typedef bool(__cdecl *OffsetComparator)(const void *UserData, size_t BlockOffset,
size_t InstructionLength, uint64_t Offset1,
uint64_t Offset2);

// If an OffsetMunger function is defined, it is called before the OffsetComparator.
// If it returns `true` then:
// 1. the instructions are considered equivalent
// 2. the offsets have been decoded and "munged" (changed), and
// *Offset1 and *Offset2 are set to the values to use.
// 3. *SkipInstructions1 instructions in code stream 1 are skipped
// 4. *SkipInstructions2 instructions in code stream 2 are skipped
//
// This is typically used on arm32 to treat "movw/movt" as a single instruction
// generating a single constant. Similarly, for arm64 mov/movk/movk/movk sequences.
typedef bool(__cdecl *OffsetMunger)(const void *UserData, size_t BlockOffset,
size_t InstructionLength, uint64_t* Offset1, uint64_t* Offset2,
uint32_t* SkipInstructions1, uint32_t* SkipInstructions2);

// The Export/Import definitions for CoreDistools library are defined below.
// A typedef for each interface function's type is defined in order to aid
// the importer.
Expand All @@ -76,6 +91,10 @@ typedef bool(__cdecl *OffsetComparator)(const void *UserData, size_t BlockOffset
typedef CorDisasm * __cdecl InitDisasm_t(enum TargetArch Target);
DllIface InitDisasm_t InitDisasm;

// Initialize the disassembler, using buffered print controls
typedef CorDisasm * __cdecl InitBufferedDisasm_t(enum TargetArch Target);
DllIface InitBufferedDisasm_t InitBufferedDisasm;

// Initialize the disassembler using custom print controls
typedef CorDisasm * __cdecl NewDisasm_t(enum TargetArch Target,
const PrintControl *PControl);
Expand All @@ -85,6 +104,28 @@ DllIface NewDisasm_t NewDisasm;
typedef void __cdecl FinishDisasm_t(const CorDisasm *Disasm);
DllIface FinishDisasm_t FinishDisasm;

// Initialize a code differ using buffered output.
typedef CorDisasm * __cdecl InitBufferedDiffer_t(enum TargetArch Target,
const OffsetComparator Comparator);
DllIface InitBufferedDiffer_t InitBufferedDiffer;

// Initialize the Code Differ
typedef CorAsmDiff * __cdecl NewDiffer_t(enum TargetArch Target,
const PrintControl *PControl,
const OffsetComparator Comparator);
DllIface NewDiffer_t NewDiffer;

// Initialize the Code Differ, with an offset munger.
typedef CorAsmDiff * __cdecl NewDiffer2_t(enum TargetArch Target,
const PrintControl *PControl,
const OffsetComparator Comparator,
const OffsetMunger Munger);
DllIface NewDiffer2_t NewDiffer2;

// Delete the Code Differ
typedef void __cdecl FinishDiff_t(const CorAsmDiff *AsmDiff);
DllIface FinishDiff_t FinishDiff;

// DisasmInstruction -- Disassemble one instruction
// Arguments:
// Disasm -- The Disassembler
Expand All @@ -100,22 +141,27 @@ typedef size_t __cdecl DisasmInstruction_t(const CorDisasm *Disasm,
const uint8_t *Bytes, size_t Maxlength);
DllIface DisasmInstruction_t DisasmInstruction;

// Initialize the Code Differ
typedef CorAsmDiff * __cdecl NewDiffer_t(enum TargetArch Target,
const PrintControl *PControl,
const OffsetComparator Comparator);
DllIface NewDiffer_t NewDiffer;

// Delete the Code Differ
typedef void __cdecl FinishDiff_t(const CorAsmDiff *AsmDiff);
DllIface FinishDiff_t FinishDiff;
// DumpInstruction -- Disassemble one instruction and output it
// Arguments:
// Disasm -- The Disassembler
// Address -- The address at which the bytes of the instruction
// are intended to execute
// Bytes -- Pointer to the actual bytes which need to be disassembled
// MaxLength -- Number of bytes available in Bytes buffer
// Returns:
// -- The Size of the disassembled instruction
// -- Zero on failure
typedef size_t __cdecl DumpInstruction_t(const CorDisasm *Disasm,
const uint8_t *Address, const uint8_t *Bytes,
size_t Maxlength);
DllIface DumpInstruction_t DumpInstruction;

// NearDiffCodeBlocks -- Compare two code blocks for semantic
// equivalence
// Arguments:
// AsmDiff -- The Asm-differ
// UserData -- Any data the user wishes to pass through into
// the OffsetComparator
// the OffsetComparator/OffsetMunger
// Address1 -- Address at which first block will execute
// Bytes1 -- Pointer to the actual bytes of the first block
// Size1 -- The size of the first block
Expand Down Expand Up @@ -145,4 +191,12 @@ typedef void __cdecl DumpDiffBlocks_t(const CorAsmDiff *AsmDiff,
const uint8_t *Bytes2, size_t Size2);
DllIface DumpDiffBlocks_t DumpDiffBlocks;

// Get a pointer to the buffered output buffer.
typedef const char* __cdecl GetOutputBuffer_t();
DllIface GetOutputBuffer_t GetOutputBuffer;

// Clear the buffered output buffer.
typedef void __cdecl ClearOutputBuffer_t();
DllIface ClearOutputBuffer_t ClearOutputBuffer;

#endif // !defined(_COREDISTOOLS_H_)
3 changes: 0 additions & 3 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
void CodeGen::genArm64EmitterUnitTestsGeneral()
{
assert(verbose);
emitter* theEmitter = GetEmitter();

//
Expand Down Expand Up @@ -1824,7 +1823,6 @@ void CodeGen::genArm64EmitterUnitTestsGeneral()
*/
void CodeGen::genArm64EmitterUnitTestsAdvSimd()
{
assert(verbose);
emitter* theEmitter = GetEmitter();

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -4557,7 +4555,6 @@ void CodeGen::genArm64EmitterUnitTestsAdvSimd()
*/
void CodeGen::genArm64EmitterUnitTestsSve()
{
assert(verbose);
emitter* theEmitter = GetEmitter();

//
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2674,8 +2674,8 @@ void CodeGen::genCodeForSetcc(GenTreeCC* setcc)
/*****************************************************************************
* Unit testing of the emitter: If JitDumpEmitUnitTests is set, generate
* a bunch of instructions, then:
* Use DOTNET_JitLateDisasm=* to see if the late disassembler thinks the instructions as the same as we do.
* Or, use DOTNET_JitRawHexCode and DOTNET_JitRawHexCodeFile and dissassemble the output file.
* Use DOTNET_JitLateDisasm=* to see if the late disassembler thinks the instructions are the same as we do.
* Or, use DOTNET_JitRawHexCode and DOTNET_JitRawHexCodeFile and disassemble the output file.
*
* Possible values for JitDumpEmitUnitTests:
* Amd64: all, sse2
Expand All @@ -2688,7 +2688,7 @@ void CodeGen::genEmitterUnitTests()
{
const WCHAR* unitTestSection = JitConfig.JitDumpEmitUnitTests();

if ((!verbose) || (unitTestSection == nullptr))
if (unitTestSection == nullptr)
{
return;
}
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,12 @@ void Compiler::compInit(ArenaAllocator* pAlloc,

void Compiler::compDone()
{
#ifdef LATE_DISASM
if (codeGen != nullptr)
{
codeGen->getDisAssembler().disDone();
}
#endif // LATE_DISASM
}

void* Compiler::compGetHelperFtn(CorInfoHelpFunc ftnNum, /* IN */
Expand Down
Loading

0 comments on commit 5455432

Please sign in to comment.