kubo39's blog

ただの雑記です。

D言語のOpenSSL事情、というか愚痴

つらい話です、というかただの愚痴です。

D言語のOpenSSLバインディングとしては D-Programming-Deimos/openssl があるのですが、メンテナンスが行き届いているとは言い難い状態です。 それ以外にもいくつか問題があって、

  • 新しめのAPIへの対応が追従できていない
  • サポートしているOpenSSLのバージョンが不明
  • リリーススケジュールが不明
  • LibreSSL対応されていない、する予定があるのかも不明
  • だれがコアのメンテナなのかわからない
  • Cヘッダからある程度自動で生成するってあるけど方法が不明、みんな手動でパッチ書いてる状況
  • スタッティックリンクできない
  • ライブラリのバージョニングが不明
  • Cヘッダ同根するメリットあるのこれ?

なんてこともあり、パッチを書くにしてもどうしたもんかという感じです。

そういう事情もあり、TLSが必要なライブラリにいたっても、

  • vibe-d: ベースはD-Programming-Deimos/openssl を使いつつも足りない箇所はバージョンによる分岐を独自実装
  • dlang-requests: 上記バインディングは使わずに動的リンク・ロードで独自実装

みたいな感じになってしまっています。

だれかイニシアチブとってやってくれると助かるんだけど、まあないだろうな。自前で新しいの書いたほうがいい気さえしてきている。。

LDCのlibFuzzerを試す

LLVMはlibFuzzerというFuzzingの仕組みがあって、LDCからその機能を使うことができる。

こういうコードで試してみる。LDCは1.19.0。

import ldc.libfuzzer;
import std.string;

mixin DefineTestOneInput!fuzz_target;

int fuzz_target(in ubyte[] data)
{
    if (data == "FU".representation)
        assert(false);
    return 0;
}

コンパイルオプションで -fsanitize=fuzzer をつけることで試せるらしい。 実行してみる。

$ ldc2 -g -fsanitize=fuzzer fuzz.d 
$ ./fuzz                 
WARNING: Failed to find function "__sanitizer_acquire_crash_state".                                           
WARNING: Failed to find function "__sanitizer_print_stack_trace".                 
WARNING: Failed to find function "__sanitizer_set_death_callback".                       
INFO: Seed: 1969889841                                       
INFO: Loaded 1 modules   (25 inline 8-bit counters): 25 [0x56393139edb0, 0x56393139edc9),
INFO: Loaded 1 PC tables (25 PCs): 25 [0x56393139edd0,0x56393139ef60),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes                      
INFO: A corpus is not provided, starting from an empty corpus                     
#2      INITED cov: 7 ft: 7 corp: 1/1b exec/s: 0 rss: 24Mb                        
        NEW_FUNC[1/1]: 0x5639313194b1                                                      
#5      NEW    cov: 9 ft: 9 corp: 2/3b lim: 4 exec/s: 0 rss: 24Mb L: 2/2 MS: 3 ChangeByte-CopyPart-InsertByte-
#4194304        pulse  cov: 9 ft: 9 corp: 2/3b lim: 4096 exec/s: 2097152 rss: 24Mb
#8388608        pulse  cov: 9 ft: 9 corp: 2/3b lim: 4096 exec/s: 1677721 rss: 24Mb                                                                                         
core.exception.AssertError@fuzz.d(10): Assertion failure
----------------                        
??:? [0x563931355425]                                              
??:? [0x563931374daa]                                                             
??:? [0x56393135bbdd]                                             
??:? [0x56393135533c]                                      
fuzz.d:10 [0x5639313192f1]                                                               
libfuzzer.di:66 [0x56393131918a]                                                                              
FuzzerLoop.cpp:553 [0x563931337486]                                                        
FuzzerLoop.cpp:469 [0x56393133d437]                          
FuzzerLoop.cpp:696 [0x56393133f62b]                       
FuzzerLoop.cpp:831 [0x5639313407aa]  
FuzzerDriver.cpp:825 [0x56393132ad79]                                                                                                  
FuzzerMain.cpp:19 [0x563931318ef2]                                                
??:? __libc_start_main [0x7f6dc7dccb96]                                           
??:? [0x563931318fa9]                                                             
uncaught exception                                                                
core.exception.AssertError@/home/kubo39/dlang/ldc-1.19.0/bin/../import/ldc/libfuzzer.di(73): Assertion failure                                                             
----------------
??:? [0x563931355425]
??:? [0x563931374daa]
??:? [0x56393135bbdd]
??:? [0x56393135533c]
libfuzzer.di:73 [0x563931319204]
FuzzerLoop.cpp:553 [0x563931337486]
FuzzerLoop.cpp:469 [0x56393133d437]
FuzzerLoop.cpp:696 [0x56393133f62b]
FuzzerLoop.cpp:831 [0x5639313407aa]
FuzzerDriver.cpp:825 [0x56393132ad79]
FuzzerMain.cpp:19 [0x563931318ef2]
??:? __libc_start_main [0x7f6dc7dccb96]                                                                                                                                    
??:? [0x563931318fa9]                                   
==5215== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.                   
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal                                 
MS: 3 ChangeBit-InsertByte-ChangeBinInt-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
0x46,0x55,                                                                               
FU                                                                                                            
artifact_prefix='./'; Test unit written to ./crash-510e70573bca51a824e345d5cff7448f740203fb
Base64: RlU=

なんだか出力の結果が怪しいが、とりあえずlibFuzzer runtime上で動いているようにみえる。

opamでnumのインストールに失敗してcoqが入らなかったのでocamlfind removeで解決した

opamでcoqをインストールしようとすると以下のようなエラーになった。

$ opam --version
2.0.5
$ opam list
# Packages matching: installed
# Name              # Installed # Synopsis
base-bigarray       base
base-threads        base
base-unix           base
camlp5              7.10        Preprocessor-pretty-printer of OCaml
conf-findutils      1           Virtual package relying on findutils
conf-m4             1           Virtual package relying on m4
ocaml               4.07.0      The OCaml compiler (virtual package)
ocaml-base-compiler 4.07.0      Official release 4.07.0
ocaml-config        1           OCaml Switch Configuration
ocamlfind           1.8.1       A library manager for OCaml
$ opam install coq                                                                                                                                              
The following actions will be performed:                                                                                                                                    
  ∗ install num 1.3     [required by coq]                                                                                                                                   
  ∗ install coq 8.10.1*                                                                                                                                                     
===== ∗ 2 =====                                                                                                                                                             
Do you want to continue? [Y/n] y                                                                                                                                            
                                                                                                                                                                            
<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>                                                                                            
[coq.8.10.1] found in cache                                                                                                                                                 
[num.1.3] found in cache                                                                                                                                                    
                                                                                                                                                                            
<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>                                                                                            
[ERROR] The installation of num failed at "make install".                                                                                                                   
                                                                                                                                                                            
#=== ERROR while installing num.1.3 ===========================================#                                                                                            
# context     2.0.5 | linux/x86_64 | base-bigarray.base base-threads.base base-unix.base ocaml-base-compiler.4.07.0 | https://opam.ocaml.org/#662359aa                      
# path        ~/.opam/4.07.0/.opam-switch/build/num.1.3                                                                                                                     
# command     ~/.opam/opam-init/hooks/sandbox.sh install make install                                                                                                       
# exit-code   2                                                                                                                                                             
# env-file    ~/.opam/log/num-16298-0a5907.env                                                                                                                              
# output-file ~/.opam/log/num-16298-0a5907.out                                                                                                                              
### output ###                                                                                                                                                              
# [...]                                                                                                                                                                     
# make[1]: ディレクトリ '/home/kubo39/.opam/4.07.0/.opam-switch/build/num.1.3/src' から出ます                                                                               
# make -C toplevel install                                                                                                                                                  
# make[1]: ディレクトリ '/home/kubo39/.opam/4.07.0/.opam-switch/build/num.1.3/toplevel' に入ります                                                                          
# sed -e 's/%%VERSION%%/1.3/g' META.in > META                                                                                                                               
# ocamlfind install num-top META num_top.cma num_top.cmi num_top_printers.cmi                                                                                               
# ocamlfind: Package num-top is already installed                                                                                                                           
#  - (file /home/kubo39/.opam/4.07.0/lib/num-top/META already exists)                                                                                                       
# Makefile:27: recipe for target 'install' failed                                                                                                                           
# make[1]: *** [install] Error 2                                                                                                                                            
# make[1]: ディレクトリ '/home/kubo39/.opam/4.07.0/.opam-switch/build/num.1.3/toplevel' から出ます                                                                          
# Makefile:14: recipe for target 'install' failed                                                                                                                           
# make: *** [install] Error 2                                                                                                                                               
                                                                                                                                                                            
                                                                                                                                                                            
                                                                                                                                                                            
<><> Error report <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>                                                                                            
┌─ The following actions failed                                                                                                                                             
│ ∗ install num 1.3                                                                                                                                                         
└─                                                
╶─ No changes have been performed

これはocamlfind内のnumが邪魔をしており、opamのnumが入らないからのようだ。 以下のように ocamlfind remove すればインストールできるようになった。

$ ocamlfind remove num num-top
Removed /home/kubo39/.opam/4.07.0/lib/num/META
Removed /home/kubo39/.opam/4.07.0/lib/num
Removed /home/kubo39/.opam/4.07.0/lib/num-top/META
Removed /home/kubo39/.opam/4.07.0/lib/num-top
$ opam install coq          
The following actions will be performed: 
  ∗ install num 1.3     [required by coq]                                       
  ∗ install coq 8.10.1*    
===== ∗ 2 =====                 
Do you want to continue? [Y/n] y
                                                                                
<><> Gathering sources ><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
[coq.8.10.1] found in cache
[num.1.3] found in cache                                                        
                                                                                                                                                      
<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>
∗ installed num.1.3                                                  
∗ installed coq.8.10.1
Done.

LDCにおいてもはや必要なくなったcopy-relocation checkのためのワークアラウンドを消した話

LDCのバグで困っている、というので調査をしてみた。

調べてみると、どうもこれはLDCで実行バイナリを生成する場合(より正確にはmain関数を定義している場合)のみ行われるcopy-relocation checkのために必要とされるようだ。

なんでcopy-relocation checkが必要とされているかというと、モジュールの衝突検出を行う際に用いられているためである。

モジュールの衝突検知は共有オブジェクトをロード/リンクした際に別のモジュール空間のModuleInfoと同一セグメントに置かれていないかどうかをチェックする機構である。 もし同一セグメント上に重なって配置してしまうとModuleInfoは(たぶん)後からロードされた共有ライブラリのほうがセグメントをひっそりと上書きしてしまうのでユーザが意図しない挙動を引き起こしたりする。 copy-relocationのロジックはあまりちゃんと読んでいないが、どうやらdruntimeを特別扱いするために必要なようだ。

しかしモジュール衝突検知はdruntimeから削除されており、そのためcopy-relocation checkももはや DMD LDC ともに存在していない。 そのためLDCはcopy-relocation checkのためのワークアラウンドなシンボル作成を必要としなくなっている。

これを削除するプルリクエストはすでに投げており、マージはしてもらえそうだがシンボル情報を使っているライブラリがあるかもしれないということでv1.19ではひとまず入らない方向となっている。

DMDのDWARFが2019年でまだv3だった

ふと、DMDが生成するデバッグ情報を調べていたところDMDはDWARF v3でデバッグ情報を付与するようだ。

DMDのバージョンは2.089.0を使っている。

$ dmd --version
DMD64 D Compiler v2.089.0
Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved written by Walter Bright
  • DWARF v3にあがったときのコミット (2015年)

[dwarf] Bump default debug version to DWARF3 by ibuclaw · Pull Request #4734 · dlang/dmd · GitHub

  • DWARF v4の拡張の定義(2015年)

Add DWARF 4 extensions by ibuclaw · Pull Request #4733 · dlang/dmd · GitHub

上記の変更でv4移行のバージョンが定義されている場合 DW_AT_MIPS_linkage_name ではなく DW_AT_linkage_name を用いるようになっているが、DMD内の定義で enum DWARF_VERSION = 3 と固定されているので DW_AT_MIPS_linkage_name が生成されている。

$ LANG=C objdump --dwarf=info helloworld| grep linkage_name| ddemangle
    <75>   DW_AT_MIPS_linkage_name: _Dmain
    <ce>   DW_AT_MIPS_linkage_name: main
    <77a>   DW_AT_MIPS_linkage_name: @safe void std.stdio.writeln!(immutable(char)[]).writeln(immutable(char)[])
    <89e>   DW_AT_MIPS_linkage_name: @safe void std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(scope immutable(char)[])
    <9c6>   DW_AT_MIPS_linkage_name: pure nothrow @nogc @safe const(char)[] std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(scope immutable(char)[]).__dgliteral2()
    <a7a>   DW_AT_MIPS_linkage_name: nothrow @nogc @trusted ulong std.stdio.trustedFwrite!(char).trustedFwrite(shared(core.stdc.stdio._IO_FILE)*, const(char[]))
    <b4d>   DW_AT_MIPS_linkage_name: @safe int std.exception.enforce!(std.exception.ErrnoException).enforce!(int).enforce(int, lazy const(char)[], immutable(char)[], ulong)
    <c34>   DW_AT_MIPS_linkage_name: @safe void std.exception.bailOut!(std.exception.ErrnoException).bailOut(immutable(char)[], ulong, scope const(char)[])
    <cdf>   DW_AT_MIPS_linkage_name: pure nothrow @property @safe immutable(char)[] object.idup!(const(char)).idup(const(char)[])
    <d71>   DW_AT_MIPS_linkage_name: pure nothrow @trusted immutable(char)[] object._trustedDup!(const(char), immutable(char))._trustedDup(const(char)[])
    <e2d>   DW_AT_MIPS_linkage_name: pure nothrow immutable(char)[] object._dup!(const(char), immutable(char))._dup(const(char)[])
    <f45>   DW_AT_MIPS_linkage_name: pure nothrow @nogc @safe void object._doPostblit!(immutable(char))._doPostblit(immutable(char)[])
    <100d>   DW_AT_MIPS_linkage_name: pure nothrow @nogc @trusted void delegate(ref immutable(char)) pure nothrow @nogc @safe object._getPostblit!(immutable(char))._getPostblit()
    <10a2>   DW_AT_MIPS_linkage_name: @safe void std.stdio.File.LockingTextWriter.put!(immutable(char)).put(immutable(char))
    <115a>   DW_AT_MIPS_linkage_name: nothrow @nogc @trusted int std.stdio.File.LockingTextWriter.put!(immutable(char)).put(immutable(char)).trustedFPUTC(int, core.stdc.stdio._IO_FILE*)
    <124d>   DW_AT_MIPS_linkage_name: nothrow @nogc @trusted int std.stdio.File.LockingTextWriter.put!(immutable(char)).put(immutable(char)).trustedFPUTWC(dchar, core.stdc.stdio._IO_FILE*)
    <131d>   DW_AT_MIPS_linkage_name: @safe void std.stdio.File.LockingTextWriter.put!(char).put(char)
    <13c6>   DW_AT_MIPS_linkage_name: nothrow @nogc @trusted int std.stdio.File.LockingTextWriter.put!(char).put(char).trustedFPUTC(int, core.stdc.stdio._IO_FILE*)
    <14a1>   DW_AT_MIPS_linkage_name: nothrow @nogc @trusted int std.stdio.File.LockingTextWriter.put!(char).put(char).trustedFPUTWC(dchar, core.stdc.stdio._IO_FILE*)
    <3410>   DW_AT_linkage_name: (indirect string, offset: 0x120): __register_atfork

__register_atforkDW_AT_linkage_name と出てきているが、これはDMDとは関連がない。

<1><340f>: Abbrev Number: 60 (DW_TAG_subprogram)
    <3410>   DW_AT_external    : 1
    <3410>   DW_AT_declaration : 1
    <3410>   DW_AT_linkage_name: (indirect string, offset: 0x120): __register_atfork
    <3414>   DW_AT_name        : (indirect string, offset: 0x120): __register_atfork
    <3418>   DW_AT_decl_file   : 42
    <3419>   DW_AT_decl_line   : 52

山陰のうまい飯 2019年

前回の帰省のタイミングでアップデート。松江・米子近郊。

松江

山美世(うなぎ)

  • おすすめ度: 9/10
  • 値段: やや高め

今松江近辺で一番美味しいうなぎはここ。 ちょっと立地がわるいかも、米子空港からは近い。 うなぎの名店は他に「いずも」や「おおはかや」などもある。

神代そば (そば)

  • おすすめ度: 10/10
  • 値段: お手頃

定番中の定番。割子蕎麦がおすすめ。 観光スポットにも近いので観光がてらに。 甘い出雲そばらしさを求めるなら近くにある「きがるそば」のほうがいいかも。

ろんぢん (ステーキ・しゃぶしゃぶ)

  • おすすめ度: 9/10
  • 値段: お高い

高級志向であればここ。島根は牛がうまいのだ。 ここも有名観光地付近なので周辺の散策を兼ねるのがいいかも。

Mr.ビーフ (ステーキ)

  • おすすめ度: 9/10
  • 値段: お高い

島根和牛のシャトーブリアンのステーキが比較的お手頃に食べられる。 ちなみに東京・銀座に姉妹店がある。

博多 (海鮮)

  • おすすめ度: 10/10
  • 値段: そこそこ

郷土料理の鯛まま・かにままをはじめ海鮮がおいしい。

晶福 (飲み屋・海鮮)

  • おすすめ度: 9/10
  • 値段: お手頃

普通の飲み屋っぽい佇まいだが、とれたての海鮮と多種の地酒がおいている。 わりと手頃な価格なのも嬉しいところ。

山陰地ビール館 (地ビール)

  • おすすめ度: 9/10
  • 値段: そこそこ

島根の地ビールが飲める場所。 私的にここのヴァイツェンがわりと好き。

喫茶きはる (和菓子)

  • おすすめ度: 10/10
  • 値段: そこそこ

和菓子職人が作る創作和菓子を楽しめる。松江を感じられるのはここが一番かな。 人間国宝だかなんだからしい?

カフェヴィータ (カフェ)

  • おすすめ度: 10/10
  • 値段: そこそこ

山陰が誇るバリスタ一家の息子・弟の店。 でかいバリスタマシンはみるだけで楽しめる。 なんといってもカフェオレがおすすめ。

クーラン・デ・エール (カフェ)

  • おすすめ度: 9/10
  • 値段: そこそこ

駅前のちょっと大人なカフェ。 コーヒー&アルコールな飲み物が名物。 自家製ケーキもgood。

出雲

吉岡製菓 (洋菓子・和菓子)

  • おすすめ度: 9/10
  • 値段: そこそこ

フルーツを使った創作菓子の店として界隈では有名。 ここは販売のみなので注意。通販でもいいかも。

安来

カフェロッソ (カフェ)

  • おすすめ度: 10/10
  • 値段: そこそこ

山陰が誇るバリスタ一家の息子・兄の店。 ここもカフェオレがおすすめ。 景色も楽しめる。

境港

境港

  • おすすめ度: 8/10
  • 値段: そこそこ~お高い

なんか海鮮いろいろ売ってる、食べれるとこもある。

米子・日吉津

ダックン・ダック (フランス料理)

  • おすすめ度: 10/10
  • 値段: やや高め

コース料理ではここ。素材にこだわった肉も魚も野菜もおいしい。 席は多くないので念の為予約はしたほうがいいかもしれない。 ランチが狙いどころか。

山芳亭 (海鮮)

  • おすすめ度: 8/10
  • お値段: そこそこ

地元民はここにいく。 境港とれたての海の幸を安価に食べられる。

ずっとdruntimeのベンチマークのコンパイルがリンカエラーで落ち続けてる

最近ちっともDMDのビルドがうまくいかない。 ホストのコンパイラとしてDMD 2.087.1にパスを通した状態で、全部(dmd,druntime,phobos)のレポジトリに make -f posix.mak clean をかけた状態でmasterを更新してdmdmake -f posix.mak -j4phobosでも make -f posix.mak -j4 する。

その状態でdruntime直下に移動して make -f posix.mak benchmark-compile-only をかけると以下のようなリンクエラーに遭遇する。

(dmd-2.087.1)$ LANG=C make -f posix.mak benchmark-compile-only
../dmd/generated/linux/release/64/dmd -conf= -m64 -I/home/kubo39/dev/dlang/druntime/import -I../phobos -L-L../phobos/generated/linux/release/64 -fPIC -defaultlib=libphobos2.so -L-rpath=../phobos/generated/linux/release/64 -de benchmark/runbench.d -ofgenerated/linux/release/64/benchmark
DMD=../dmd/generated/linux/release/64/dmd generated/linux/release/64/benchmark --repeat=0 --dflags="-conf= -m64 -I/home/kubo39/dev/dlang/druntime/import -I../phobos -L-L../phobos/generated/linux/release/64 -fPIC -defaultlib=libphobos2.so -L-rpath=../phobos/generated/linux/release/64 -de"
generated/linux/release/64/benchmark: symbol lookup error: generated/linux/release/64/benchmark: undefined symbol: _D4core8internal5array5utils12__ModuleInfoZ
posix.mak:346: recipe for target 'benchmark-compile-only' failed
make: *** [benchmark-compile-only] Error 127

この現象がいつまでたってもなおらない。おかげでrunbench.dでなんでパッチが落ちるのかの原因調査ができない。 もうずっとこんな調子で嫌気がさしてきた。CIは動いているので、なんか自分のところの環境が変なんだろうけどまるっきり見当がつかない。

とにかくこんな調子じゃ開発なんてできやしない。

追記

cloneしなおしてきてもできなかったが、dmd 2.086.1をホストにしたら make -f posix.mak benchmark-compile-only が成功した。dmd 2.087.0以降のregression?