銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

Y8 2017 spring in Shibuya で .NET Core on Linux の内部について話しました

Y8 2017 Spring という技術系ノンジャンル(と私は理解している)イベントがあったので登壇してきました。CFPにリアクションして頂いたみなさまありがとうございました。こちらが資料です(更新するかもしれないです)。

doc.co

イベントサイトはこちら。

y8-2017-spring.hachiojipm.org

.NET Core がLinux(やmacOS)で動くようにどうやって実装しているかとか、デバッグの仕方とか、OS固有の部分をどうやってLinuxの世界に持ち込んでいるのか、というテーマはずっと話したくて機会を伺っていたのですがようやく世に出すことができました。

もし次があれば、デバッグまわりの部分はもう少し実践的な内容にしたいなあと思います。また、Linuxユーザー向けにはVisual Studio側の機能紹介もしたいですね。今回デモしたように、.NET CoreをLinuxにデプロイする場合でも、Windowsで開発することができ、リモートデバッグすることができます。また、リモートデバッグについてはいつの間にかやたらリモートデバッグの接続の種類が増えているので、改めて調査します。

f:id:tanaka733:20170527164325p:plain

dllに含まれるシグニチャを見るには?

質問されて答えが出せなかったので、いったん調べた内容をこちらに。dllの中で定義されているクラスとかメソッド一覧を取得したいという質問だったのですが、dllの中に定義されているのはIL(中間言語)なのでnmコマンドなどでは見れないはずです。あくまで.NET CoreのILを解釈する必要があります。Windows上の.NET FrameworkならILSpyなどのフリーのツールで逆コンパイルすることもできるのですが、Linux上で動作する.NET Core向けの逆コンパイルツールは見つけられませんでした。

ILSpy

とりあえずできそうな方法はLLDBでlibsospluginをsosコマンドからたどって行く方法です。.NET Coreのlibsospluginの使い方の詳細はこちらにあります。

github.com

定義されているsosコマンドは.NET Frameworkのものと対応しており、その詳細はこちらに書いてあります。

SOS.dll (SOS デバッガー拡張)

ではこれを使って、stringクラスのメソッド一覧を出してみましょう。ちなみにsosコマンドあまり詳しくないので、よりよい方法があればコメントなどをもらえるとうれしいです。

DumpHeapでstringを指定します。

(lldb) sos DumpHeap string
         Address               MT     Size
00007f6b1aed5000 00000000010717b0       24 Free
00007f6b1aed5018 00000000010717b0       24 Free
00007f6b1aed5030 00007f6d3b77db68       72     
(以下略)

どれか1つのアドレスを指定してDumpObjします。

(lldb) sos DumpObj 00007f6b1aed50b8
Name:        System.String
MethodTable: 00007f6d3b77db68
EEClass:     00007f6d3b0916d0
Size:        60(0x3c) bytes
File:        /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/System.Private.CoreLib.ni.dll
String:      Format_GuidDashes
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007f6d3b797948  4001aa6        8         System.Int32  1 instance               17 m_stringLength
00007f6d3b7827c0  4001aa7        c          System.Char  1 instance               46 m_firstChar
00007f6d3b77db68  4001aa8     1258        System.String  0   shared           static Empty
                                 >> Domain:Value  00000000010e3fb0:NotInit  <<

メソッド一覧はMethodTableで取得できます。詳細を出すために--mdを指定します。

(lldb) sos DumpMT -md 00007f6d3b77db68 
EEClass:         00007F6D3B0916D0
Module:          00007F6D3B00B000
Name:            System.String
mdToken:         00000000020005AD
File:            /opt/dotnet/shared/Microsoft.NETCore.App/1.1.1/System.Private.CoreLib.ni.dll
BaseSize:        0x18
ComponentSize:   0x2
Slots in VTable: 196
Number of IFaces in IFaceMap: 7
--------------------------------------
MethodDesc Table
           Entry       MethodDesc    JIT Name
00007F6D3B42CE10 00007F6D3B0E1508 PreJIT System.String.ToString()
00007F6D3B42E3F0 00007F6D3B0E17A8 PreJIT System.String.Equals(System.Object)
00007F6D3B42EA60 00007F6D3B0E1878 PreJIT System.String.GetHashCode()
00007F6D3B41EE10 00007F6D3B0DF0B0 PreJIT System.Object.Finalize()
00007F6D3B42CE20 00007F6D3B0E1510 PreJIT System.String.ToString(System.IFormatProvider)
00007F6D3B42CE30 00007F6D3B0E1518 PreJIT System.String.Clone()
00007F6D3B42CF40 00007F6D3B0E1550 PreJIT System.String.GetTypeCode()
00007F6D3B42CF50 00007F6D3B0E1558 PreJIT System.String.System.IConvertible.ToBoolean(System.IFormatProvider)
(以下略)

まあ、めんどくさいですね… これはもう少し調べてみることにします。