Greetings,
First, about the problem / task:
Having started writing another debugger plugin for the retro platform under IDA Pro (secretly: it will be SNES), I came across the following set that needed to be friends:
- The emulator kernel is written in C ++ and compiled into a DLL
- The emulator GUI is written in C # and uses a kernel DLL to control the emulation.
- IDA Pro, , C++ DLL ( C++)
- IDA ( , , ..) , IDA .
( ), :
1) LoadLibrary("emu_core.dll")
, GetProcAddress(core, "Pause")
pause()
, , , .
: — ( , GUI )! , , , , DLL-, , , UI, .
, DLL- IDA, . .
2) - -, , — GUI, RPC-.
, :
- IDA (, , reset), .. , , , .
- . , , , , RPC .
COM. , , RPC . , , WinAPI (.. C/C++) — C#.
.. GUI , . COM-.
:
1) , COM, [ComVisible(true)]
. , - , ( , , )
2) , , ( IDA). ( ComVisible
):
[Guid("7710855F-D37B-464B-B645-972BAB2706D4")] // Visual Studio GUID-
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
public interface IDebugApi
3) , DebugCOM
:
[Guid("6AF9F5DD-6626-4E35-BEF4-29A73E18A739")]
[ComVisible(true)]
public class DebugCOM : IDebugApi
4) ( ) (Class Library
), . DebugCOM.dll
5) tlbexp.exe Visual Studio ( Developer Command Prompt
) DLL TLB. , ..
:
tlbexp DebugCOM.dll /out:DebugCOM.tlb
COM, :
Assembly exported to 'DebugCOM.tlb'
, . :
TlbExp : warning TX801311B0 : Type library exporter warning processing 'AddressInfo.Type, DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'InteropBreakpoint.MemoryType, DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.GetMemorySize(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.GetMemoryValue(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.SetMemoryValue(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.SetMemoryValues(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.SetMemoryState(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.GetMemoryState(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.GetMemoryAccessCounts(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
TlbExp : warning TX801311B0 : Type library exporter warning processing 'IDebugApi.GetMemoryAccessCounts2(type), DebugCOM'. Warning: Non COM visible value type 'SnesMemoryType' is being referenced either from the type currently being exported or from one of its base types.
, SnesMemoryType
ComVisible(true)
. .
6) TLB- (File->View TypeLib...
) ComView. :
c:\Windows\Microsoft.NET\Framework\v4.0.30319\ComView.exe
IDL:
File->Save as...
IDL-.
7) IDL- C++ , , , DebugCOM
:
8) IDL- Compile Ctrl+F7
. , : DebugCOM_h.h
DebugCOM_i.c
. ( ), .
, C# , . C/C++. C#.
9) - .h
.c
, , . :
#include <atlbase.h>
#include <iostream>
#include "DebugCOM_h.h"
#include "DebugCOM_i.c"
int main(int argc, char* argv[]) {
HRESULT hr;
hr = ::CoInitializeEx(0, COINITBASE_MULTITHREADED);
if (FAILED(hr))
{
std::cout << "CoInitializeEx failure: " << std::hex << std::showbase << hr << std::endl;
return EXIT_FAILURE;
}
CLSID CLSID_server;
hr = ::CLSIDFromString(L"{6AF9F5DD-6626-4E35-BEF4-29A73E18A739}", &CLSID_server);
if (FAILED(hr))
{
std::cout << "CLSIDFromString failure: " << std::hex << std::showbase << hr << std::endl;
return EXIT_FAILURE;
}
CComPtr<IDebugApi> server;
hr = ::CoCreateInstance(CLSID_server, nullptr, CLSCTX_LOCAL_SERVER, __uuidof(IDebugApi), (void**)&server);
if (FAILED(hr))
{
std::cout << "CoCreateInstance failure: " << std::hex << std::showbase << hr << std::endl;
return EXIT_FAILURE;
}
DebugState state = {};
hr = server->GetState(&state);
if (FAILED(hr))
{
std::cout << "GetState failure: " << std::hex << std::showbase << hr << std::endl;
return EXIT_FAILURE;
}
std::cout << "PC Address: " << std::hex << std::showbase << state.Cpu.PC << std::endl;
::CoUninitialize();
return EXIT_SUCCESS;
return 0;
}
COM.
COM-
:
- Inprocess
- Out-of-process
, COM , . , COM GUI, IDA.
COM DLL.
, COM- . , , , -. .. , COM .
, out-of-process COM. , GitHub " " : https://github.com/dotnet/samples/tree/master/core/extensions/OutOfProcCOM. .
As a result, I managed to make IDA Pro and the .NET Framework application friends with Windows tools, without fussing bikes from my own RPC protocols. In addition, I solved the problem of having only one copy of the emulator kernel and sharing its state between several applications.