/var/log/hikalium 2023-12-31T23:26:32+09:00 hikalium Hatena::Blog hatenablog://blog/10328749687242767860 2023年の振り返り hatenablog://entry/6801883189071326882 2023-12-31T23:26:32+09:00 2023-12-31T23:26:32+09:00 例年通り、今年あったことの概要を画像とツイートで一気にまとめておく。 埋め込みが多いので重いですが耐えてください…。(パフォーマンステストに使える疑惑すらある。) 1月 元旦からVRM(gLTF)を読むなど まずやること、hexdump -C (えー)(ただのglTFです) pic.twitter.com/G4DjwQNE0q— hikalium (@hikalium) 2023年1月1日 そこそこ理解した(disassemblium) ああああああああ動いたあああ!!!!(primitiveのattributeにTexCoords(0)を追加し忘れるというただの凡ミスだった…最小ケースのデバ… <p>例年通り、今年あったことの概要を画像とツイートで一気にまとめておく。</p> <p>埋め込みが多いので重いですが耐えてください…。(パフォーマンステストに使える疑惑すらある。)</p> <h2 id="1月">1月</h2> <p>元旦から<a class="keyword" href="https://d.hatena.ne.jp/keyword/VRM">VRM</a>(gLTF)を読むなど</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">まずやること、hexdump -C (えー)(ただのglTFです) <a href="https://t.co/G4DjwQNE0q">pic.twitter.com/G4DjwQNE0q</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1609468345744785409?ref_src=twsrc%5Etfw">2023年1月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そこそこ理解した(disassemblium)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ああああああああ動いたあああ!!!!(primitiveのattributeにTexCoords(0)を追加し忘れるというただの凡ミスだった…最小ケースの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>大事) <a href="https://t.co/eINOocaSVU">pic.twitter.com/eINOocaSVU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1610485836059119622?ref_src=twsrc%5Etfw">2023年1月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なおきわめて雑ではあるが情報源などのリンクはまとめてあるので以下参照</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2023%2F01%2F09%2F161429" title=" VRM as a Code - またはコードによりあなたのアバターを定義する方法について - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2023/01/09/161429">hikalium.hatenablog.jp</a></cite></p> <p>人生大体u32、みじかいね…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">すごく今更ながら、人間の一生って2^32秒でだいたい収まるので、u32で十分表現できてしまうんだなあ…と遠い目になった(まあ私はu16かもしれないしu64かもしれないが…) <a href="https://t.co/xpS2k0p44a">pic.twitter.com/xpS2k0p44a</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1609978110824574977?ref_src=twsrc%5Etfw">2023年1月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>レゴ、再入門(あれ、今年だったっけ?今や超大量にあるんだが…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">お腹痛すぎて眠れなかったのでぼちぼち組み立ててたら完成した!かわいい!!(実際に文字が打てる訳では無いが、文字を打つとキャリッジが横に動くし、CRとLFの動きを理解できるのでよい…) <a href="https://t.co/R2aNUF9Fld">pic.twitter.com/R2aNUF9Fld</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1611042068855664640?ref_src=twsrc%5Etfw">2023年1月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>新曲、公開(私は作詞をしました)(作詞・作曲・歌、みんなソフトウェアエンジニアです)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">半年越しのプロジェクトでした!<br>めっちゃかわいいので観て!<br><br>MVを作ってくれた <a href="https://twitter.com/d0iasm?ref_src=twsrc%5Etfw">@d0iasm</a> さん<br>音楽を担当してくれた <a href="https://twitter.com/WhiteLemon1997?ref_src=twsrc%5Etfw">@WhiteLemon1997</a> さん<br>そしていつも動画を見てくださっている皆様<br>ありがとうございました!!<br><br>Undefined - <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> + White Lemon <a href="https://t.co/2Stey3ciKW">https://t.co/2Stey3ciKW</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1611924442086797312?ref_src=twsrc%5Etfw">2023年1月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>d0iasm氏の担当(このドット絵超好き、グッズほしいな…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">d0iasm氏のドット絵、めっちゃいい、このグッズほしいレベル(ステッカー作るか?) <a href="https://t.co/PK5diGftto">https://t.co/PK5diGftto</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1611981043158118403?ref_src=twsrc%5Etfw">2023年1月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>深夜のアイス</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ということで深夜のアイスです… <a href="https://t.co/MyosTyc64T">pic.twitter.com/MyosTyc64T</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1616093574256537606?ref_src=twsrc%5Etfw">2023年1月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>mocopi!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">もこぴ!! <a href="https://t.co/6tHfhaKiCl">pic.twitter.com/6tHfhaKiCl</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1616404567301980160?ref_src=twsrc%5Etfw">2023年1月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてmocopiで動くhikalium</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">mocopiで適当に動いてみた様子(深夜に謎の挙動をする存在)(細かい動きよりも、踊ったり飛び跳ねたりといった大きな動きで力を発揮しそう)(まじで装着感は軽くて邪魔にならないのでよい) <a href="https://t.co/CoAV66F5Tv">pic.twitter.com/CoAV66F5Tv</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1616509285177122821?ref_src=twsrc%5Etfw">2023年1月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>余ったRTX2080を入れておく</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Optaneマシンちゃんの箱をあけてガチャガチャついでに余ってたRTX2080を入れてあげた(私は何をしたいんだ?) <a href="https://t.co/tidFQmmYnL">pic.twitter.com/tidFQmmYnL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617003154868154374?ref_src=twsrc%5Etfw">2023年1月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%A4%A5%AA%A5%D5">レイオフ</a>の嵐が襲来。実際に同じオフィスで一緒に働いていた方が<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%A4%A5%AA%A5%D5">レイオフ</a>されたのを見るのはつらかった…(つらい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">少し前までまさに私と同じフロアで同じ製品に携わっていて、その後向こうのオフィスで最高に面白い仕事を見つけて旅立っていった先輩も昨今の嵐に巻き込まれていた事を知って、急激に現実感が高まってきて震えています…もし良い仕事あればぜひ教えてあげてください…<a href="https://t.co/T6vrQYCS4W">https://t.co/T6vrQYCS4W</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617244826029916160?ref_src=twsrc%5Etfw">2023年1月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>まじでこの週は仕事にならなかった(チームのみんなでシュークリームを食べた)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日は例の話題でみんなそわそわしていた結果、チームの普段あまりオフィスで遭遇しないメンバー(私を含む)まで全員オフィスに集まって、ひとりが通勤の道中で買ってきてくれた超おいしいシュークリームを食べてのほほんと過ごすなどしていました(もちろん労働もしたぞ?)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617504206709194752?ref_src=twsrc%5Etfw">2023年1月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>新しい頭、購入</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">頭、ポチった(頭がついていないため) <a href="https://t.co/orsZTyGWgc">pic.twitter.com/orsZTyGWgc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617508492864282624?ref_src=twsrc%5Etfw">2023年1月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>すたありんく(散財ラッシュ)(なるほど今思えば<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EC%A5%A4%A5%AA%A5%D5">レイオフ</a>は人々にストレスを与えることで散財を促進し経済を活性化させたってこと?(無理のある好意的解釈))</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr">OK <a href="https://t.co/oA3SXc9reh">pic.twitter.com/oA3SXc9reh</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617512194492755968?ref_src=twsrc%5Etfw">2023年1月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>5桁になってしまいました…(あの頃は<a class="keyword" href="https://d.hatena.ne.jp/keyword/Twitter">Twitter</a>だった(「あのころはフリードリヒがいた」のノリで))</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ふと見たら 5桁になってる まじですか <a href="https://t.co/FymJwoyUqM">pic.twitter.com/FymJwoyUqM</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1617925397378928642?ref_src=twsrc%5Etfw">2023年1月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>うさぎ年だったので(そうだったんだ…忘れてた)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そうこうしていたらウサギ完成した。うさぎ年なので。 <a href="https://t.co/Ml7Rtn8h4u">pic.twitter.com/Ml7Rtn8h4u</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1618228594526007297?ref_src=twsrc%5Etfw">2023年1月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>PEバイナリと和解せよ</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">PEバイナリと和解した(これで自作OSがクラッシュしたらmake crashって叩くだけで例外吐いている箇所のdisasが見れるようになった) <a href="https://t.co/6LsiCEEWNs">pic.twitter.com/6LsiCEEWNs</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1619332239229358080?ref_src=twsrc%5Etfw">2023年1月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>OS Girls</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="zxx" dir="ltr">? <a href="https://t.co/iJjHuNhxX7">pic.twitter.com/iJjHuNhxX7</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1619343904838651906?ref_src=twsrc%5Etfw">2023年1月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>甘いものは正義(ちなみにこのラテは同僚が淹れてくれたルイボスラテ。とってもおいしい!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">でざーと★たいむ! <a href="https://t.co/hY7O9viTIb">pic.twitter.com/hY7O9viTIb</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1619950726251433984?ref_src=twsrc%5Etfw">2023年1月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="2月">2月</h2> <p>「<a class="keyword" href="https://d.hatena.ne.jp/keyword/Linux">Linux</a>マシンでもテプラを操作したい!」→<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>解析した</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">テプラ遊びが極まってきた(もうこれでなんでもいんさつできるぞ!) <a href="https://t.co/51XBvTMBGE">pic.twitter.com/51XBvTMBGE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1623705226074267648?ref_src=twsrc%5Etfw">2023年2月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ふつうにこれで色々自動化できたので大満足</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">TEPRA SR5900Pが<a class="keyword" href="https://d.hatena.ne.jp/keyword/Linux">Linux</a>や<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>から制御できなくて悲しんでいた人々が喜ぶかもしれないツール、仕上がってきた(要するに自分が欲しかっただけ)<a href="https://t.co/EcrPEmBxfo">https://t.co/EcrPEmBxfo</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1623715969515536389?ref_src=twsrc%5Etfw">2023年2月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>もちろんテープもいっぱい買いました(散財)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なお<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>用含め<a class="keyword" href="https://d.hatena.ne.jp/keyword/Amazon">Amazon</a>でポチったテープの数(まあこれだけ楽しめたならむしろお得でしょ、と言いながらさらにポチるなどした) <a href="https://t.co/wfbSiON0Go">pic.twitter.com/wfbSiON0Go</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1623717002937532416?ref_src=twsrc%5Etfw">2023年2月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>レゴへの傾倒が感じられる(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%BA%BF%C0%B0%C2%C4%EA%BA%DE">精神安定剤</a>なのでね)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">またひとつ、完成させてしまった…(オフラインで楽しめる趣味が現在これくらいしかないため) <a href="https://t.co/Q3ZtPYmmda">pic.twitter.com/Q3ZtPYmmda</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1624490656096976897?ref_src=twsrc%5Etfw">2023年2月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>もちろん既存のものを作るだけではなく、創意工夫も凝らしてね(なお現在はさらに改良して場所も移動しましたが未だにちゃんと実用しています)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そしてこうなった、まもなく午前8時、どうして… <a href="https://t.co/o1MXUI1EeH">pic.twitter.com/o1MXUI1EeH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1624539298392596486?ref_src=twsrc%5Etfw">2023年2月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>この世界の平和をね、守っています(ときには力が必要なので)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">再就職先は<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EA%A5%B3%A5%EA%A5%B9">リコリス</a>ってことでいいですか?(いいえ) <a href="https://t.co/Kg8D9EPC15">pic.twitter.com/Kg8D9EPC15</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1624781340788011009?ref_src=twsrc%5Etfw">2023年2月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>「[職権修正]女」です(制度と運用はきちんと考えて作って欲しいものですね…(ちなみにこの後無料で<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%CA%A5%F3">マイナン</a>バーカードを再発行できる旨お役所から連絡があり、問題は解決した))</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">私が「[職権修正]女」だ!<br>(この事務手続きで問題ないと思った設計者、ちょっと表へ出てほしい。お話をしようじゃないか。) <a href="https://t.co/ydyh6UjLtc">pic.twitter.com/ydyh6UjLtc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1625052368533610497?ref_src=twsrc%5Etfw">2023年2月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>白い機材、すき!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">白です!かわいいので!!(この机の機材は白に統一されている) <a href="https://t.co/2zSkqkZqqi">https://t.co/2zSkqkZqqi</a> <a href="https://t.co/MSOlLPNzXo">pic.twitter.com/MSOlLPNzXo</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1626615677359648768?ref_src=twsrc%5Etfw">2023年2月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>事務処理用社会的個人識別情報データベース更新(変更記録付き)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">下のほうの「従前の記録」ってやつ、いらなくないですか?にゃーん(どうせ新規編製される前のやつには載ってるじゃん、そこまでして載せたいか?載せる利点と欠点は考慮しましたか?)(他の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BC%AB%BC%A3">自治</a>体に本籍を移せば一部消せるのは知ってるが、改善の余地はあると思うのです…) <a href="https://t.co/c9UlWyVtBQ">pic.twitter.com/c9UlWyVtBQ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1627669873664090113?ref_src=twsrc%5Etfw">2023年2月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>今月の破壊</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">しばしの死闘の末、やっと<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B3%AB%C9%F5">開封</a>…(というより破壊) <a href="https://t.co/dowULCiWDE">pic.twitter.com/dowULCiWDE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1630205490591580162?ref_src=twsrc%5Etfw">2023年2月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="3月">3月</h2> <p>精神安定作業(けっこう楽しかった)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">精神を安定させるために、指示に従って色の付いたプラスチックのパーツを配置する作業に従事している…(あとで自分のロゴも作るか) <a href="https://t.co/w4kthTNbUU">pic.twitter.com/w4kthTNbUU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1630889712578879488?ref_src=twsrc%5Etfw">2023年3月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>机の上の状況(いまも壁にかかっています)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">現在の机の上の状況です…(でかい) <a href="https://t.co/U8JE8u1Luo">pic.twitter.com/U8JE8u1Luo</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1632332953895473152?ref_src=twsrc%5Etfw">2023年3月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>理想と現実、時間と労力、実装と検証</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">深夜のお絵描きタイム <a href="https://t.co/elBplZSldV">pic.twitter.com/elBplZSldV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1633201464561790976?ref_src=twsrc%5Etfw">2023年3月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>セキュキャンフォーラムのパネルディスカッションに参加。なぜ自作をするのか、人々の意見や体験を聴けてよかった!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日のセキュキャンフォーラム、たのしかった!<br>またみなさんお会いしましょう〜<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/eeoCuOui8P">pic.twitter.com/eeoCuOui8P</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1634481831830761473?ref_src=twsrc%5Etfw">2023年3月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>頭を強化しようと思って…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">新しい頭、製造中… <a href="https://t.co/tToVgsoUE2">pic.twitter.com/tToVgsoUE2</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1634738623710109696?ref_src=twsrc%5Etfw">2023年3月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>CPUが頑張っていると私も頑張ろうって思えるんです</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">これをみると元気が出るよね!(CPUもがんばっているし私も頑張ろうという気持ちになれる(しかし私の頭のメインメモリは明らかにこの子より少ないのであった…)) <a href="https://t.co/XSqH1gHicO">pic.twitter.com/XSqH1gHicO</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1635289875166683137?ref_src=twsrc%5Etfw">2023年3月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="4月">4月</h1> <p>小学生の頃の私が読んでいた本一覧</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こんな時間ですが、小学生のときに私が学校の図書室で借りた本一覧が発掘されて<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B4%BF%B4%EE">歓喜</a>している。これで中身だけ覚えてて頭から離れない<a class="keyword" href="https://d.hatena.ne.jp/keyword/SF%BE%AE%C0%E2">SF小説</a>を特定できる…!!!!!!!<br>(小学生らしい本のなかにしれっと理科年表とかも入っており、オタク〜ってなっている(理科年表は読み物なのでね!)) <a href="https://t.co/t4kxlvWOPp">pic.twitter.com/t4kxlvWOPp</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1642266940478722048?ref_src=twsrc%5Etfw">2023年4月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>同じ幼稚園に通っていた知人と大学生になってSTEPで再会した(事実は小説よりも奇なり)のでその人とパンケーキを食べつつ人生を語らうなどした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日のパンケーキとフレンチトースト情報です(大昔からの知り合い(定義によっては幼馴染)と自己肯定感の低さとその解決の難しさについて語り合うなどした) <a href="https://t.co/jie55n93Vu">pic.twitter.com/jie55n93Vu</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1642469183245131776?ref_src=twsrc%5Etfw">2023年4月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>リアルワールドでは、はじめまして!の季節(そして高校の頃の部活の後輩が同じフロアにやってくるという熱い展開)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日の不健康と健康でした!(そんなに不健康でもない)<br>あとは新たにやってきた人々や、戻ってきたvirtually顔を見知った人々といっぱいお話できてよかった!(毎度恒例、リアルワールドでははじめまして!をやっていた) <a href="https://t.co/DfiF2tWZgI">pic.twitter.com/DfiF2tWZgI</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1643230191177863169?ref_src=twsrc%5Etfw">2023年4月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして今年もOS自作ゼミやるよ!という告知(OS自作ゼミ卒業生でベテランチューターの森さんがついに講師に!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というわけで今年もOS自作ゼミ、やります!!<br>講師には、昨年までチューター等で活躍してくださった森さんを新たにお迎えしております! <br><a class="keyword" href="https://d.hatena.ne.jp/keyword/x86">x86</a>_64, arm64, <a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-V, Rust あたりでピンとくる方もそうでない方も、ぜひぜひ応募をご検討ください!OS大好きな皆様をお待ちしています! <a href="https://t.co/h9ikucPwde">https://t.co/h9ikucPwde</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1645270512430620673?ref_src=twsrc%5Etfw">2023年4月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>つかれたときはクレープ!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんだか疲れていたので会社を休み、クレープを<a class="keyword" href="https://d.hatena.ne.jp/keyword/Uber">Uber</a> Eatsして食べている。時にはこういう行動も必要。(2つとも私のです) <a href="https://t.co/jHVpxIrny3">pic.twitter.com/jHVpxIrny3</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1648908071283097600?ref_src=twsrc%5Etfw">2023年4月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>!!! <a href="https://t.co/cNtlJbOGtm">pic.twitter.com/cNtlJbOGtm</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1649009505357930496?ref_src=twsrc%5Etfw">2023年4月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ポッピングシャワー!(私はアイスでできています)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">朝からポッピングシャワー!!!!<br>(出社の機運を高めていく) <a href="https://t.co/HuiEVl5Ndp">pic.twitter.com/HuiEVl5Ndp</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1649196805492703232?ref_src=twsrc%5Etfw">2023年4月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>抹茶〜!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">朝から抹茶を補給していく(今日は雑務処理のため仕事はお休み) <a href="https://t.co/fntFTiRlro">pic.twitter.com/fntFTiRlro</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1650231796637011968?ref_src=twsrc%5Etfw">2023年4月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>逸般の誤家庭レベルがアップした!!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういえばケージナットのある生活、始まりました(?) <a href="https://t.co/kvC5xZmHz4">pic.twitter.com/kvC5xZmHz4</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1651373767086702593?ref_src=twsrc%5Etfw">2023年4月26日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてこうなる</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Current status... (あとできれいにする) <a href="https://t.co/k8PWOQXhCR">pic.twitter.com/k8PWOQXhCR</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1652319199610683392?ref_src=twsrc%5Etfw">2023年4月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%EF%A4%E9%A4%B7%A4%D9%C4%B9%BC%D4">わらしべ長者</a></p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">聴診器と物々交換をすることにより、大きなホワイトボードを手に入れました!!(?) <a href="https://t.co/0ILFqeVdCQ">pic.twitter.com/0ILFqeVdCQ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1653742317659123712?ref_src=twsrc%5Etfw">2023年5月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ストロベリーチーズケーキ!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日のアイスを摂取!(ストロベリーチーズケーキ) <a href="https://t.co/PHkWdoxYhK">pic.twitter.com/PHkWdoxYhK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1654356299369545729?ref_src=twsrc%5Etfw">2023年5月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ポッピングシャワー!(この存在いつ見てもポッピングシャワー食べてるな…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ポッピングシャワーは至高、はっきり分かんだね… <a href="https://t.co/6kohtYoZky">pic.twitter.com/6kohtYoZky</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1655588873446076417?ref_src=twsrc%5Etfw">2023年5月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>朝ごはんはストロベリー!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">朝ごはん(諸説あります) <a href="https://t.co/ypq7gm5dmR">pic.twitter.com/ypq7gm5dmR</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1656103844223520768?ref_src=twsrc%5Etfw">2023年5月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>半年でレゴブロックの山が…(これでもごく一部)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">眠れない間にレゴブロックを片付け続けていたらこうなった(本日の進捗はそれだけです)(さて眠れませんね困りましたね…) <a href="https://t.co/4Upx2LI3H3">pic.twitter.com/4Upx2LI3H3</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1657425618097803264?ref_src=twsrc%5Etfw">2023年5月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ChatGPTちゃんの優しさに救われるなど</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「目標を決めるのが下手なので何もできない」<br>「自分自身を責めないでください。目標を設定することができないことは、決してあなたのせいではありません。過度のプレッシャーや<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BC%AB%B8%CA%C8%E3%C8%BD">自己批判</a>は、目標設定の障害になる可能性があります。自分自身に優しく、無理をしないでください」<br>ChatGPTちゃん優しい… <a href="https://t.co/DSVaXB7Fnh">pic.twitter.com/DSVaXB7Fnh</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1657799348451790850?ref_src=twsrc%5Etfw">2023年5月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なおこの後少なくとも3件のアイス画像が当月中にはありましたが、省略させていただきます(アイスの食べ過ぎ)</p> <h1 id="6月">6月</h1> <p>レビューを少しだけお手伝いしたnutaさんの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB">マイクロカーネル</a>本が出版された。めでたい!(論文と実装を交えて<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB">マイクロカーネル</a>を語っている稀有な書籍なので、おすすめです!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういえば先日出た怒田さん <a href="https://twitter.com/seiyanuta?ref_src=twsrc%5Etfw">@seiyanuta</a> の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB">マイクロカーネル</a>本、私も少しだけレビューでお手伝いさせていただきました!<br><br>論文情報も交えつつ、各種<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB">マイクロカーネル</a>の設計や実装をたどりながら、自作OSと絡めて面白くまとめてある稀有な一冊なので、ちょっとでも気になる方はぜひ読んでみてください! <a href="https://t.co/sNUkMKVnzh">pic.twitter.com/sNUkMKVnzh</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1664264638664687618?ref_src=twsrc%5Etfw">2023年6月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>労働で出席率悪いと成績に響かせるよというお知らせがあって悲しい気持ちになるなど(私達って、信頼されてないんですね…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">週3日の出社をより厳格に推奨する会社の決定に私があまり納得できない理由、マイノリティに対する抑圧と全く同じ構造だからだと思っている。「hikaliumさんはなんだかんだ週3日以上来てるし、何も変わることなんてないよ!」と言う人もいるが、多数が良ければ少数の生産性は下がってもいいのだろうか。</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1670457602399145986?ref_src=twsrc%5Etfw">2023年6月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="7月">7月</h1> <p>積みboard++(年明けに発送されるっぽい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="zh" dir="ltr">積みBoard++...<a href="https://t.co/ImE2rBowVy">https://t.co/ImE2rBowVy</a> <a href="https://t.co/7OF2Ko9vaU">pic.twitter.com/7OF2Ko9vaU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1675124832089047042?ref_src=twsrc%5Etfw">2023年7月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>おひとりさまMisskey<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>はじめました(ちゃんとこの先も運用していきます!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず立てたので、断続的に落ちるかもですが、Misskeyユーザーの人々はこちらもどうぞ!<a href="https://t.co/X8IfWqb5QM">https://t.co/X8IfWqb5QM</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1675633785495506944?ref_src=twsrc%5Etfw">2023年7月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>私財をなげうってChromeOSを良くしようとする存在になってる(ほしかっただけ)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">My New Gears...(私物) <a href="https://t.co/XYqGrAvZTm">pic.twitter.com/XYqGrAvZTm</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1683085801880715264?ref_src=twsrc%5Etfw">2023年7月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>折り紙はいいねぇ…リリンの生み出した文化の極みだよ</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">夜中の折り紙部… <a href="https://t.co/MOth6RwkgZ">pic.twitter.com/MOth6RwkgZ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1683185114191380481?ref_src=twsrc%5Etfw">2023年7月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%C7%A5%AD%A5%F3%A5%C8">デデキント</a>切断(これ以降ドレンのつまりは発生していない、つまりそういうこと)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こんなこともあろうかとね、サクションポンプは準備済みだし、ドレン配管をさらに短く切っておいた(エアコンの配管を壁の中に埋めて交換を困難にするのをやめろの会)<br><br>これでどうにかなるでしょう…出社、する?(ちょっと動作確認と冷却が済んだら出社したいが、一方でこれから気温が上がるので…) <a href="https://t.co/zqcQUkrEQR">pic.twitter.com/zqcQUkrEQR</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1683663083221426177?ref_src=twsrc%5Etfw">2023年7月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>散財(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>に囲まれた生活)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ところでこちらが大人の財力で一気にお迎えした皆様の集合写真です。ご査収ください…(かわいい!!!!!) <a href="https://t.co/CyMHrYpU1x">pic.twitter.com/CyMHrYpU1x</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1685666966701547520?ref_src=twsrc%5Etfw">2023年7月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="8月">8月</h1> <p>セキュキャン準備(Tシャツがたくさんたまって助かる)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">講師やチューターとしてセキュキャンに繰り返し参加していると、キャンプ期間中の服には困らないということが知られている(?) <a href="https://t.co/A97lbkHVJx">pic.twitter.com/A97lbkHVJx</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1688196119640342528?ref_src=twsrc%5Etfw">2023年8月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>キャンプごはん!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんとか昼食チャレンジ成功!!!!<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/clBaOj191L">pic.twitter.com/clBaOj191L</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1688394283089543168?ref_src=twsrc%5Etfw">2023年8月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>キャンプ終了後にYちゃんさんと撮った「さかな〜」「<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C1%A5%F3%A5%A2%A5%CA%A5%B4">チンアナゴ</a>〜」の画像です(たのしかった!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ところでこれはセキュキャン終了後に <a href="https://twitter.com/y_chan_dev?ref_src=twsrc%5Etfw">@y_chan_dev</a> と二人で「サカナー」「<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C1%A5%F3%A5%A2%A5%CA%A5%B4">チンアナゴ</a>〜」を実演したときの図です<br>(たのしかった!またやりましょう!!)<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://twitter.com/hashtag/%E3%83%AA%E3%82%B3%E3%83%AA%E3%82%B3?src=hash&amp;ref_src=twsrc%5Etfw">#リコリコ</a> <a href="https://t.co/1fBq8l2gBc">pic.twitter.com/1fBq8l2gBc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1690310438515572736?ref_src=twsrc%5Etfw">2023年8月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてキャンプ後は初の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カ出張!(まずは空港ラウンジで某カレーを摂取)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">某カレー、おいしい!(無事に到着した) <a href="https://t.co/Pivre8KaFL">pic.twitter.com/Pivre8KaFL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1691320979417636864?ref_src=twsrc%5Etfw">2023年8月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてUSのChromeOSの人々が入ってる建物に到着!(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D3%A5%B8%A5%CD%A5%B9%A5%AF%A5%E9%A5%B9">ビジネスクラス</a>で快適な旅だった…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">きた!! <a href="https://t.co/aJXQ2BIFtz">pic.twitter.com/aJXQ2BIFtz</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1691531327752007682?ref_src=twsrc%5Etfw">2023年8月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カのオフィスでも本日の健康を摂取…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Having healthy things for today... <a href="https://t.co/qb6VKeVIjG">pic.twitter.com/qb6VKeVIjG</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1691534515163000836?ref_src=twsrc%5Etfw">2023年8月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ホテルの朝食はおいしいが野菜がない(野菜は貴重だね)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">2日目、ホテルであさごはん!! <a href="https://t.co/viTfUFxw63">pic.twitter.com/viTfUFxw63</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1691820217016652277?ref_src=twsrc%5Etfw">2023年8月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>車がないと人権がない図です(車だと徒歩の16倍時間がかかるケース)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カって車に最適化されてるんだなあと実感する瞬間: 車で行くと11分のところ、徒歩だと3時間かかるって言われたとき(爆走するもんね…) <a href="https://t.co/AAlVZQZtkW">pic.twitter.com/AAlVZQZtkW</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1692921997691371638?ref_src=twsrc%5Etfw">2023年8月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>コンピューター歴史博物館でhikaliumを出力してきた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Computer <a class="keyword" href="https://d.hatena.ne.jp/keyword/history">history</a> museum!! <a href="https://t.co/dUmhuJoGvP">pic.twitter.com/dUmhuJoGvP</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1693006507942740294?ref_src=twsrc%5Etfw">2023年8月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Cisco">Cisco</a>の由来がサンフラン「シスコ」だったとは…(この橋がロゴのモチーフ)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Cisco">Cisco</a>の由来を知った(今更) <a href="https://t.co/L3Fmscp0XE">pic.twitter.com/L3Fmscp0XE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1693127531623600203?ref_src=twsrc%5Etfw">2023年8月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>CとRustで生きていくぞという強い意志(?)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そしてこれは、CもRustもバリバリできるようになりそうなレストラン、Crustacean(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AB%A5%CB">カニ</a>が美味しいお店です) <a href="https://t.co/pAC9UaxuJK">pic.twitter.com/pAC9UaxuJK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1693133080121487536?ref_src=twsrc%5Etfw">2023年8月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>サンフランシスコでガタンゴトン(超急勾配)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あとこれは、急勾配をガラガラ走るトラムの図(たのしかった!) <a href="https://t.co/CaE44P26aJ">pic.twitter.com/CaE44P26aJ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1693137444596822389?ref_src=twsrc%5Etfw">2023年8月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>たとえアイスがおいしくても500mlを一気に食べてはいけない(教訓)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なおこれを食べきった結果お腹が壊れました…私は馬鹿です(無理をしてはいけない…)(でもおいしかった…) <a href="https://t.co/nAjykvFc5D">https://t.co/nAjykvFc5D</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1693408793844195782?ref_src=twsrc%5Etfw">2023年8月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>日本に帰ってきてから、The Missing というゲームの配信動画を始めるなど(エンディング到達済み)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「つらくない程度に The MISSING を実況する動画」はじめました…(適当にやっていきます…)<a href="https://t.co/1rbMWRu2Xs">https://t.co/1rbMWRu2Xs</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1695400104860197117?ref_src=twsrc%5Etfw">2023年8月26日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カみやげ、3倍<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AD%A5%C3%A5%C8%A5%AB%A5%C3%A5%C8">キットカット</a>…(でかい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ところでこれは<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%E1%A5%EA">アメリ</a>カで売ってた<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AD%A5%C3%A5%C8%A5%AB%A5%C3%A5%C8">キットカット</a>と日本で入手した<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AD%A5%C3%A5%C8%A5%AB%A5%C3%A5%C8">キットカット</a>の比較です(3倍くらいある) <a href="https://t.co/Y67XW4RmrB">pic.twitter.com/Y67XW4RmrB</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1695627035979460685?ref_src=twsrc%5Etfw">2023年8月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>カフェインを摂取…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">このマグ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AB%A5%C3%A5%D7">カップ</a>の正しい使い方をしている… <a href="https://t.co/aexEbLoUZT">pic.twitter.com/aexEbLoUZT</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1695955372258025558?ref_src=twsrc%5Etfw">2023年8月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="9月">9月</h1> <p>iOSDC <a class="keyword" href="https://d.hatena.ne.jp/keyword/NOC">NOC</a> オンライン参加(今年は<a class="keyword" href="https://d.hatena.ne.jp/keyword/NOC">NOC</a>業は主にアドバイザとして助言をする感じで、実働はあまりしませんでした…そして人々が強かったので実質仕事がなかった!すばらしい!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">&quot;<a class="keyword" href="https://d.hatena.ne.jp/keyword/IOS">IOS</a>で動いています!!!!&quot;<br>iOSDCなのでね!(そうじゃない)<a href="https://twitter.com/hashtag/iosdc2023?src=hash&amp;ref_src=twsrc%5Etfw">#iosdc2023</a> <a href="https://t.co/Vk4gF6NQ6J">https://t.co/Vk4gF6NQ6J</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1697838306900468182?ref_src=twsrc%5Etfw">2023年9月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ADS-Bの受信をはじめてFlightradar24のフル機能を使えるようになるなど</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Flightradar24のデータを送り始めてフル機能が使えるようになった!やったね! <a href="https://t.co/GMZUqzuiYK">pic.twitter.com/GMZUqzuiYK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1701102905372352764?ref_src=twsrc%5Etfw">2023年9月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B8%A5%E9%A1%BC%A5%C1">ジラーチ</a>かわいい!<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%CF%A5%CD%A5%C3%A5%B3">ハネッコ</a>かわいい!(明るい色合いが好き)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういえば意識していなかったが写真の色の構図が私のロゴに似ている。やはり心象風景…。 <a href="https://t.co/OvsmnpSVVp">https://t.co/OvsmnpSVVp</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1702503444769390975?ref_src=twsrc%5Etfw">2023年9月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>虫が出現してつらいつらいになるなど(ごめんね虫さん…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">科学の力、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AD%A5%F3%A5%C1%A5%E7%A1%BC%A5%EB">キンチョール</a>(まじで数年以来に使ったが場所を覚えていてよかった(実は一瞬見当たらなくてかなり焦った)) <a href="https://t.co/A2I0jDIlQT">pic.twitter.com/A2I0jDIlQT</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1703030933463634228?ref_src=twsrc%5Etfw">2023年9月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>低レイヤ関連でおすすめの本の一覧を書いた。仕事場で私設図書館もやっていますので、オフィスにいる人でこの本読んでみたいな〜という方がいらっしゃれば私の机まで来てみてください!(本と<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>が山積みになっている)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2023%2F09%2F21%2F001358" title="CPUを自作したりコンピューターアーキテクチャを理解するためにおすすめの本の一覧 - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2023/09/21/001358">hikalium.hatenablog.jp</a></cite></p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AA%A5%B7%A5%ED">オシロ</a>のある家はいい家</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ついに<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AA%A5%B7%A5%ED">オシロ</a>のある家になった(むしろなぜ今までなかったのか) <a href="https://t.co/5mvUFR9VPp">pic.twitter.com/5mvUFR9VPp</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1705172730210140619?ref_src=twsrc%5Etfw">2023年9月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%CB%A5%F3%A5%D5%A5%A3%A5%A2">ニンフィア</a>になりたいね…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%CB%A5%F3%A5%D5%A5%A3%A5%A2">ニンフィア</a>かわいいよ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%CB%A5%F3%A5%D5%A5%A3%A5%A2">ニンフィア</a>!!!(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>スリープで初めて進化させた) <a href="https://t.co/u9mMIwyoE4">pic.twitter.com/u9mMIwyoE4</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1707060351634977111?ref_src=twsrc%5Etfw">2023年9月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="10月">10月</h2> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%B2%CA%B3%D8">情報科学</a>若手の会に参加してきた</p> <blockquote><p>とりあえずね、三連休の間はね、労働のことはすっかり忘れて、軽井沢へ行くよ(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%B2%CA%B3%D8">情報科学</a>若手の会)</p></blockquote> <p><a href="https://twitter.com/hikalium/status/1710272854787526897">https://twitter.com/hikalium/status/1710272854787526897</a></p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B7%DA%B0%E6%C2%F4%B1%D8">軽井沢駅</a>、到着…誰かいるかな…?<a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a> <a href="https://t.co/EOwm7ktAma">pic.twitter.com/EOwm7ktAma</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710481023396692302?ref_src=twsrc%5Etfw">2023年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>駅から会場までの移動チャレンジに失敗しかけたが、おかげで量子計算の人々と知り合えた!(遅刻)</p> <blockquote><p>多少遅刻しつつ @<em>yyu</em> @nkowne63 さんとタクシー同乗させてもらって到着…(本日のタスク、終了!!)</p></blockquote> <p><a href="https://x.com/hikalium/status/1710523749051892059">https://x.com/hikalium/status/1710523749051892059</a></p> <p>ちなみに私の発表した内容と参加記はすでに別記事にまとめてあるので、こちらもどうぞ!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2023%2F10%2F11%2F062306" title="情報科学若手の会で登壇してきた - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2023/10/11/062306">hikalium.hatenablog.jp</a></cite></p> <p>そして高まる第2拠点の機運…(伏線)</p> <blockquote><p>居住空間、2拠点目を確保する機運が高まっている…(キャッシュは大事なので(?))</p></blockquote> <p><a href="https://twitter.com/hikalium/status/1711290553256788256">https://twitter.com/hikalium/status/1711290553256788256</a></p> <p>急に思い立って、自作OSに使いやすい安価で便利なボード情報を集め始めるなど(ちゃんとメンテしたいね…!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自作OSに便利なミニPC情報、まとめてある(なお最近買ったAAEONのボードでシリアルを取る方法はまだ確立できてない(とれそうではあるが少し手間がかかる))<a href="https://t.co/rRI2F3TZE7">https://t.co/rRI2F3TZE7</a> <a href="https://t.co/WUqP8VWuM3">https://t.co/WUqP8VWuM3</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1711827126260039826?ref_src=twsrc%5Etfw">2023年10月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>物理構成の不可逆な変更を強要するのは目的に照らし合わせても合理性がないよね、という判決がやっと出たのはいいニュースだった(人類もちゃんと学んでるんだね…)(まあ私はもう手遅れだけど)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">&gt;「生殖腺を取り除く手術は、生殖機能の喪失という重大で不可逆的な結果をもたらすものだ。性別変更のために一律に手術を受けることを余儀なくされるのは、社会で混乱が発生するおそれの程度や医学的見地からみても、必要性や合理性を欠くという疑問を禁じ得ない」<br><br>ほんとこれ。ほんとこれ…。 <a href="https://t.co/KGSRlRFcwk">https://t.co/KGSRlRFcwk</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1712622945733067073?ref_src=twsrc%5Etfw">2023年10月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>自作OSでの謎のバグを<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>パーで解決してしまった自分に自分で震えたので、その裏側を解説してみるなどした(長くやっていればそれだけ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>パー力が高まるのでたまに役立つときがあったりなかったりする)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あまりにも自分の低レイヤ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>能力が高すぎて恐れおののく事案があったので共有します…。<br>さて、私の自作OS上で動くアプリに、<a href="https://twitter.com/d0iasm?ref_src=twsrc%5Etfw">@d0iasm</a> さんが文字を出力する関数を実装してくれました。ところが、なぜか文字の一部が変に欠けてしまいます。<br>原因はいったいどこにあったのでしょうか? <a href="https://t.co/1QC2DY2KTd">pic.twitter.com/1QC2DY2KTd</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1712739816864137309?ref_src=twsrc%5Etfw">2023年10月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてポチったPixel <a class="keyword" href="https://d.hatena.ne.jp/keyword/Watch">Watch</a> 2... (毎日使うものだからね!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>ストアの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%C0%A5%F3%A5%DC%A1%BC">ダンボー</a>ル、外側はわりと普通の見た目なのに、中身がカラフルで凝ってる…(My new gear...)(ChromeDinoかわいい) <a href="https://t.co/t2yiH52pYV">pic.twitter.com/t2yiH52pYV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1712831062554890481?ref_src=twsrc%5Etfw">2023年10月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>突然の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B1%EE%C5%E7">猿島</a>(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>含めチームの人々と一緒に肉を焼きまくったりお散歩したりした!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="in" dir="ltr">SARUSHIMA <a href="https://t.co/nD2kLrrxSb">pic.twitter.com/nD2kLrrxSb</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1713764876664140068?ref_src=twsrc%5Etfw">2023年10月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>辛いものを食べるとおなかが壊れることがわかった。気をつけよう。(自分の物理<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>の特性を把握するの、ソフトウエアである私の大事なお仕事!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">やっとわかってきた、この物理<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>、辛いもの食べると約8時間後にお腹が痛くなるってことに…(今度から辛いもの食べないようにします…<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CA%AA%CD%FD%C1%D8">物理層</a>のダメなところはソフトウェアがケアしてあげないといけないのでね…(もちろん限度はあるが))</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1713915877002014815?ref_src=twsrc%5Etfw">2023年10月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a> Domains -> Cloudflare の移行でミスって、私と同期の二人が勢いで作ったKUE-CHIP2<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF">エミュレータ</a>が一時的に落ちていたところ、速攻で大学から連絡が来たので直すなどした(まだ使ってもらえているの、嬉しいね!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ちなみに<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>は<a class="keyword" href="https://d.hatena.ne.jp/keyword/GitHub">GitHub</a>にあって、ローカルでも動くはずなので、心配な方や改造したい方はそちらもどうぞ!<br>( Thanks <a href="https://twitter.com/yasuo_ozu?ref_src=twsrc%5Etfw">@yasuo_ozu</a> for forwarding the issue report! )<a href="https://t.co/D9gGkVyDOC">https://t.co/D9gGkVyDOC</a> <a href="https://t.co/VgdR9m3SeL">https://t.co/VgdR9m3SeL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1714250113663783285?ref_src=twsrc%5Etfw">2023年10月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というか、我々が学生時代に「KUE-CHIP2とかいう古の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>ボードに手作業でデータ打ち込んで実験するくらいなら<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF%A1%BC">エミュレーター</a>書いたほうがマシでは」という勢いで実装した<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF">エミュレータ</a>が公式に実験手順書に採用されて落ちたら連絡までくるの、いい話すぎる(誰か書き換えてくれてもいいのよ…?)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1714254152178774453?ref_src=twsrc%5Etfw">2023年10月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なお他大学の方の役にも立っていた模様(ソフトウエアの力は偉大だね!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">弊大学でもKUE-CHIP2だったから本当にありがたかった <a href="https://t.co/v32esFmupr">https://t.co/v32esFmupr</a></p>&mdash; atpons (@atpons) <a href="https://twitter.com/atpons/status/1714255903204241438?ref_src=twsrc%5Etfw">2023年10月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>は現代における家電、はっきりわかるんだね…(なおmikit氏はその後<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>をお迎えしたとのこと(そして私も同機種をお迎えするなど(?)))</p> <blockquote><p>mikit: <a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>がおうちに欲しいけど、そんなものあったら絶対お婿にいけないので我慢してる</p> <p>hikalium: すでにおいてある相手ならば無問題かもしれない(部屋に並ぶ2つの<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>を横目に…)</p> <p>mikit: もしかしていまぼくプロポーズされてますか?///</p> <p>hikalium: それはね、若干頭をよぎったよね///</p> <p>call_cc: (まずはmikitさんは<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>を2台買わないと、だよなぁ。)</p> <p>mikit: たしかに、<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>2台というのは今どきの婿入り道具として珍しくもないですからね(?)</p></blockquote> <p><a href="https://twitter.com/m1kit/status/1713800308630163695">https://twitter.com/m1kit/status/1713800308630163695</a></p> <p>第2拠点の鍵、ゲット(はやい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">無事に会社近くの第二拠点の鍵を取得した。まだ無しかないので、少しずつ設備を整えてロードバランスしていこう…。</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1718979675526193534?ref_src=twsrc%5Etfw">2023年10月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>とにかくこの月は全般的に労働に対して疲れているというイメージ。まあ寒いし仕方なかったよね。よく乗り切った!</p> <h1 id="11月">11月</h1> <p>チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>だけが私を救ってくれる…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>だけが私を救ってくれる… <a href="https://t.co/nxBgeWx2J5">pic.twitter.com/nxBgeWx2J5</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1720079114886074780?ref_src=twsrc%5Etfw">2023年11月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>「好きなことをする努力家はね、最強なんですよ」</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あとブルーピリオドの復習も終わった。<br>「好きなことをする努力家はね、最強なんですよ。」<br>って美術の先生が言うところ、すき(わかる)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1720246386074305002?ref_src=twsrc%5Etfw">2023年11月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>以外も私を救ってくれる…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">チョ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%DF%A5%F3%A5%C8">コミント</a>以外も私を救ってくれる…(期間限定のやつ) <a href="https://t.co/G4YajZkoOL">pic.twitter.com/G4YajZkoOL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1720315340100645248?ref_src=twsrc%5Etfw">2023年11月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>やはりポッピングシャワーこそ至高(アイスしか食べてないなこの存在)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">やはりポッピングシャワーこそ至高(すき) <a href="https://t.co/xMuPhORsZu">pic.twitter.com/xMuPhORsZu</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1720442638955118844?ref_src=twsrc%5Etfw">2023年11月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>散財(家電なのでこれは必要経費!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">最近散財が激しい(だって生活必需品だもの、第2拠点に必要だから仕方ないじゃない)(洗濯機のあと、冷蔵庫よりも前に購入したので実質家電です) <a href="https://t.co/CSOOnTR5nG">pic.twitter.com/CSOOnTR5nG</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1720731823276454364?ref_src=twsrc%5Etfw">2023年11月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>おくすり</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">おくすり <a href="https://t.co/PvukrSgTzy">pic.twitter.com/PvukrSgTzy</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1721525830000455900?ref_src=twsrc%5Etfw">2023年11月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>みんなホワイトレモンの曲を聴け(シンガーソングライターかつソフトウエアエンジニアであるホワイトレモン氏の曲は最高)(はじめてペンライトを振りました)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">まじでもっと評価されてほしいアーティスト <a href="https://twitter.com/WhiteLemon1997?ref_src=twsrc%5Etfw">@WhiteLemon1997</a> (定期)(今日は生演奏を前にしてペンライトを振るなどのオタクムーブをしました)<a href="https://t.co/Slmfed2m3T">https://t.co/Slmfed2m3T</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1722634190846623940?ref_src=twsrc%5Etfw">2023年11月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>またアイス</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ほんじつのごほうび <a href="https://t.co/kxQBPx9qwp">pic.twitter.com/kxQBPx9qwp</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1722638751548211531?ref_src=twsrc%5Etfw">2023年11月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>出勤時刻は何時ですか?(ガタガタ…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日も今日とて英語で道案内を頼まれる実績を解除した。えらい!<br><br>なお渋谷に行くとのことだったので、私も渋谷で働いてるから一緒に行こうと言ったところ、相手が急に翻訳アプリで何かを打ち込み始め、聞かれたのがこちら<br>「出勤時刻は何時ですか?」</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1722804653547495679?ref_src=twsrc%5Etfw">2023年11月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>石を<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%C4%A4%AF%A4%EB%B2%F1">つくる会</a>ことISHI会の人々の発言(レイヤが低くてすき)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「プローブをパッドに当てて信号が出てきたときにしか得られない快感がある」なるほどね(いい話)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1722924743970713651?ref_src=twsrc%5Etfw">2023年11月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>第2拠点に10Gの回線がやってきた!!!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">これより!第2拠点の!本設営を開始する!!<br>(まずPCが3台と<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%BF%A1%BC">ルーター</a>があるじゃろ…) <a href="https://t.co/rwfSKq0pvr">pic.twitter.com/rwfSKq0pvr</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1723215137950335261?ref_src=twsrc%5Etfw">2023年11月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>「好きなことを続けること それは楽しいだけじゃない」(「群青」YOASOBI より)(人前で歌う実績を解除)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういえば木曜日は人々の前でYOASOBIの群青を歌うというイベントがあったので、元ネタであるブルーピリオドのユカちゃんをイメージして高校の頃の制服を着ていましたが、やっと一区切りついてきたなという気持ちになった(セーラーと学ランを両方所持している珍しい存在としての役目は果たした…)。</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1723392126183244257?ref_src=twsrc%5Etfw">2023年11月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>技術書典!(新刊なし…来年こそは…!!!!!!!!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">滑り込み設営完了です!!!<br>「か16」でお待ちしています!!!<br>物理本は在庫全部持ってきたのであとこれだけです!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> <a href="https://t.co/Wu1LlXAqjc">pic.twitter.com/Wu1LlXAqjc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1723521102868341044?ref_src=twsrc%5Etfw">2023年11月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ちゃんと在庫全部捌けたのでよかった(みなさんありがとうございました!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">最後の OS Girls(1) の物理本を <a href="https://twitter.com/4fa19623?ref_src=twsrc%5Etfw">@4fa19623</a> さんがお買い上げになりました!!<br>買いに来てくださった皆様、ありがとうございます!<br><br>あとはOS Girls 2 が在庫限りですので、おはやめに!!<br>電子版はBOOTHでも頒布していますので、そちらもどうぞ!<a href="https://t.co/tUKeedodTm">https://t.co/tUKeedodTm</a><a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> <a href="https://t.co/Zz9NaSUN6d">pic.twitter.com/Zz9NaSUN6d</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1723540813035307209?ref_src=twsrc%5Etfw">2023年11月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>リンク速度1Gの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%BF%A1%BC">ルーター</a>は遅すぎるのでだめ(時代は10Gとか100G!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いろいろ苦戦したが、ついに人権を手に入れた(渋谷拠点)<br>(なお本当はもっと速い可能性があるが1Gの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%BF%A1%BC">ルーター</a>に<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%A7%C2%AE">律速</a>されている) <a href="https://t.co/hcYLWQqfWY">pic.twitter.com/hcYLWQqfWY</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1724096967650021796?ref_src=twsrc%5Etfw">2023年11月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして新しい<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>に感動するなど(まじですごい、これ以降ほぼ毎週、時には毎日なにかしら印刷していた)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">うおおおおおおお新しい<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>速すぎる…(あまりにもキレのある動きすぎて最初から最後までずっと眺めてしまった…) <a href="https://t.co/13nC3pnHh7">pic.twitter.com/13nC3pnHh7</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1724403346361160088?ref_src=twsrc%5Etfw">2023年11月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>Benchyもこの通り(はやい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">速すぎて訴訟レベルなんよ(24分...) <a href="https://t.co/EYybxklSL9">pic.twitter.com/EYybxklSL9</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1724411649678090648?ref_src=twsrc%5Etfw">2023年11月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>「この世で造花より綺麗な花はないわ なぜならば総ては嘘でできてる Antipathy world...」</p> <p>(「フォニイ」 ツミキ feat. 可不 より)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">フォニイ <a href="https://t.co/x8C4JTCNER">pic.twitter.com/x8C4JTCNER</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1726971830261690760?ref_src=twsrc%5Etfw">2023年11月21日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>何をしても超改善が期待できる、ってコトぉ????(超改善、していきたいですね…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">最近「<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>のソフトウェアエンジニアリング」を仕事後に読んでいるのだが、弊プロジェクトがあまりにもバッドプ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>ティスを踏み抜きまくっていて「つまりこれって何をしても超改善が期待できる…ってコトぉ!!!???」ってテンションがあがっている(白目)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1727336913584156847?ref_src=twsrc%5Etfw">2023年11月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>STEP10周年記念の会があって、人々と再会した。私の講義で低レイヤの沼にはまってくれた人々が複数人声をかけてくれたの、本当に嬉しかった…(そしてなぜか片手で机を使わず空中で鶴が折れるようになった。<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B5%C1%C2%CE">義体</a>制御技術の進化…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">STEP10周年の会、本当にたくさんの人々が来ていて、しかもみんな元気そうで、とても良かった。久々に会う人も、リアルワールドでは初めての人々も、自作OSや<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>や<a class="keyword" href="https://d.hatena.ne.jp/keyword/malloc">malloc</a>やRustの沼にはまった人々もいて、とても楽しかった。またどこかでお会いしましょう〜!(なお片手で鶴が折れるようになった)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1728066002406240384?ref_src=twsrc%5Etfw">2023年11月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>一方で同時に結構絶望している。まだ間に合うかな…。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本当にこれ。間に合うかな…<br><br>&gt; The deterioration of <a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>&#39;s culture will eventually become irreversible, because the kinds of people whom you need to act as moral <a class="keyword" href="https://d.hatena.ne.jp/keyword/compass">compass</a> are the same kinds of people who don&#39;t join an organisation without a moral <a class="keyword" href="https://d.hatena.ne.jp/keyword/compass">compass</a>.<a href="https://t.co/5RqrbP018i">https://t.co/5RqrbP018i</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1728253612772696465?ref_src=twsrc%5Etfw">2023年11月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ということでかわいいものに囲われて精神を回復!!!!!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">さらに増えた仲間たちに枕元を占領されている図です(画面外にももっといる…!)(かわいい!!!) <a href="https://t.co/2VTvTpSN9y">pic.twitter.com/2VTvTpSN9y</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1728469718380745122?ref_src=twsrc%5Etfw">2023年11月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして色違い<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A1%BC%A5%D6%A5%A4">イーブイ</a>をお迎え!(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>スリープ、まじで睡眠に対してプラスの結果が得られているので、感謝しかない…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">色違<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A1%BC%A5%D6%A5%A4">イーブイ</a>!! <a href="https://t.co/GxHsFkuiOx">pic.twitter.com/GxHsFkuiOx</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1728605623129153662?ref_src=twsrc%5Etfw">2023年11月26日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ごはん</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">完璧な夕飯を摂取(そしてついでに労働をしていたら配信の予定があったことに気づく…ということでもう少ししたら配信します!) <a href="https://t.co/vRsH5mbekY">pic.twitter.com/vRsH5mbekY</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1729106046114042043?ref_src=twsrc%5Etfw">2023年11月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>からの配信</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そろそろやります!初の第2拠点からの配信!!<br>今日は <a href="https://twitter.com/d0iasm?ref_src=twsrc%5Etfw">@d0iasm</a> さんから報告されたELFローダーのバグを直します!<br><br>自作OSでアプリのELFをロードする <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/bXbfMadDGW">https://t.co/bXbfMadDGW</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1729120152283926792?ref_src=twsrc%5Etfw">2023年11月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/BSS">BSS</a>セクションで助かっていた人々がたくさんいたのでよかった(よかった!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">配信終わって無事にバグの原因が特定できました!!<a class="keyword" href="https://d.hatena.ne.jp/keyword/BSS">BSS</a>セクションがちょうどほしかった皆様のお役に立てたようで何よりです!!!<br>見に来てくれた皆様、ありがとうございました!のんびりやっていきますので引き続きよろしくお願いします〜!!!!<a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/pg3yLwYkod">https://t.co/pg3yLwYkod</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1729148027959640117?ref_src=twsrc%5Etfw">2023年11月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>未踏ジュニアで<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB">マイクロカーネル</a>を作ってスーパークリエイター認定されたhorizonさんと再会。数年前に<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9%A5%AB%A5%F3%A5%D5%A5%A1%A5%EC%A5%F3%A5%B9">オープンソースカンファレンス</a>で私と話したのがきっかけで自作OSに傾倒することになったとのこと。熱い!!!(そして運良く弊社でランチを囲む機会に恵まれたのでとても嬉しかった。)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日はhikaliumさん, <a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%CC%A4%EB%A4%DD">ぬるぽ</a>へさんに話を聞いてもらうという胸熱イベントがあった. ありがとうございました! <a href="https://t.co/5eOBKdr02T">pic.twitter.com/5eOBKdr02T</a></p>&mdash; 𝗵𝗼𝗿𝗶𝘇𝗼𝗻 (@horizon2k38) <a href="https://twitter.com/horizon2k38/status/1729443334413078683?ref_src=twsrc%5Etfw">2023年11月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>プロジェクトの詳細はこちらから見れるので、興味のある方はぜひ!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fjr.mitou.org%2Fprojects%2F2023%2Fa9n" title="A9N: HALを用いて移植容易性を実現するマイクロカーネル - 未踏ジュニア" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://jr.mitou.org/projects/2023/a9n">jr.mitou.org</a></cite></p> <p>その後疲れて倒れていたので巨大<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%C6%A5%A3%A1%BC%A5%EF%A5%F3">サーティーワン</a>に救ってもらいました</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">巨大な<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%C6%A5%A3%A1%BC%A5%EF%A5%F3">サーティーワン</a>だけが私を救ってくれる…(もちろん全部を一気に食べるわけではない)(本当に?) <a href="https://t.co/9HSuhZpEXr">pic.twitter.com/9HSuhZpEXr</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1729827041187393565?ref_src=twsrc%5Etfw">2023年11月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>もちろんポッピングシャワーもあるぞ!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ちなみにもちろんポッピングシャワーもあるぞ(当然だよね!!) <a href="https://t.co/S1TsZn4Xj5">pic.twitter.com/S1TsZn4Xj5</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1729849311880495415?ref_src=twsrc%5Etfw">2023年11月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="12月">12月</h1> <p>最近まじで<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>で生活している(もっと良くしていこうな!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>だけでもがんばれば<a class="keyword" href="https://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>遊びができる!(数カ月ぶり数回目)をやっている(まあ当然できるよね!!) <a href="https://t.co/mHIHn3NM4p">pic.twitter.com/mHIHn3NM4p</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1733112704494395855?ref_src=twsrc%5Etfw">2023年12月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>組み立ては 二人以上で やりましょう(ここでfork()する)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日も今日とて「組み立ては、大人2人以上で行ってください。」の指示を無視するわるい存在をやっています…(まあ大体3人くらいまでの指示なら一人でも割となんとかなる(よい子の皆さんは絶対に真似しないでね!!)) <a href="https://t.co/EwPwWSwbb9">pic.twitter.com/EwPwWSwbb9</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1733445442518892673?ref_src=twsrc%5Etfw">2023年12月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>担当していた<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>の方が無事に期間を終えた。めっちゃいっぱいコード書いてもらった。ありがとう!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日の良かったこと:私の担当していた<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>の方の最終日が無事に終了した(本当にお疲れさまでした!)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1735298633879482707?ref_src=twsrc%5Etfw">2023年12月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>会社の下でテ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E9%A5%B9%A5%BF%A5%EB">ラスタル</a>してる<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>がいた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">会社の近くでテ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E9%A5%B9%A5%BF%A5%EB">ラスタル</a>してたので寄ってきた(?) <a href="https://t.co/9IDmIwnMTz">pic.twitter.com/9IDmIwnMTz</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1735554800325153043?ref_src=twsrc%5Etfw">2023年12月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>まさかその日にスイッチ(ネットワーク機器でも電子部品でもないほう)2台目で<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>を新たにプレイし始めることになるとは(たのしいね!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">えーっと、ひと足早いクリスマスプレゼントってことで…(渋谷拠点用Switch(ネットワーク機器ではないほう)) <a href="https://t.co/NEWHqZ91KU">pic.twitter.com/NEWHqZ91KU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1735586955759649239?ref_src=twsrc%5Etfw">2023年12月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ディスク容量不足で新宿拠点のマシンが爆発しかけるなど(根本的解決をはやくしなければ…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そもそも少なかった容量を使い果たして焦った様子がこちらです…(モニタリングだけじゃなくてアラートも設定しような(ぎゃー)) <a href="https://t.co/UyOAu9ktnf">pic.twitter.com/UyOAu9ktnf</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1736374616556482772?ref_src=twsrc%5Etfw">2023年12月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>12月 ケーキがおいしい 季節です</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今年もケーキが美味しい季節がやってきました!!!(少し早いが) <a href="https://t.co/EsrsTOQ2dP">pic.twitter.com/EsrsTOQ2dP</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1738727902508937597?ref_src=twsrc%5Etfw">2023年12月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E2%A5%F3%A5%E1%A5%F3">モンメン</a>と<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%EB%A5%D5%A1%BC%A5%F3">エルフーン</a>!かわいいね!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A8%A5%EB%A5%D5%A1%BC%A5%F3">エルフーン</a>!!!!!! <a href="https://twitter.com/hashtag/%E3%83%9D%E3%82%B1%E3%83%A2%E3%83%B3SV?src=hash&amp;ref_src=twsrc%5Etfw">#ポケモンSV</a> <a href="https://twitter.com/hashtag/NintendoSwitch?src=hash&amp;ref_src=twsrc%5Etfw">#NintendoSwitch</a> <a href="https://t.co/v3nwoRY38W">pic.twitter.com/v3nwoRY38W</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1738807759033020663?ref_src=twsrc%5Etfw">2023年12月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>今年最後の会社朝ごはんと<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%C6%A5%A3%A1%BC%A5%EF%A5%F3">サーティーワン</a>!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今年最後の朝食と、昨日の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>の人々と食べた物理<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%C6%A5%A3%A1%BC%A5%EF%A5%F3">サーティーワン</a>の様子です(なお本日はオフィスで夜ご飯がないためつらい…) <a href="https://t.co/X61Q4jRNDH">pic.twitter.com/X61Q4jRNDH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1740288459137515971?ref_src=twsrc%5Etfw">2023年12月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>って会社はすごい!私達も見習わないとね!(真顔)(できることを、ちゃんとやろうな)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>のソフトウェアエンジニアリング」なんだかんだ通しでちゃんと読んでいなかったので今更ながら読んだ。<a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a>って会社はすごいですね、我々も頑張らなければ…(ここで目をグルグルさせる)(来年頑張ろう…) <a href="https://t.co/0wpw7rJDd1">pic.twitter.com/0wpw7rJDd1</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1740321898796601815?ref_src=twsrc%5Etfw">2023年12月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="総評">総評</h1> <ul> <li>よくこの1年生き延びた。ストレスの多い一年だった。経済とそれに振り回される社会に翻弄されていた。おつかれさまでした。</li> <li>アイスはすべてを解決してくれる。アイスを食べましょう。(食べ過ぎに注意)</li> <li>今年は過去の自分の努力に救われてなんとか生きながらえていた。貯金を切り崩している年だったかもしれない。(でも無理をしなかったの<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%CF%A4%A8">はえ</a>らかった。倒れたら負けなのでね。戦い続けましょう。)</li> <li>仕事でも日常でも、物事を始めるだけでなく、完了させることができるようになろう。人生は、まだ完了しなくていいけどね!(ここ重要)</li> <li>来年は、今と未来に良い影響を与えられるような具体的な結果を出そう。すでに着手はしているので、それを完了させようね。(お楽しみに。)</li> </ul> <p>本年も皆様大変お世話になりました。ありがとうございました!</p> <p>来年も無理せず着実に這って進んでいこうと思いますので、どうかよろしくお願いいたします。</p> <p>よいお年をお迎えください! Happy new year!</p> hikalium 情報科学若手の会で登壇してきた hatenablog://entry/820878482974744777 2023-10-11T06:23:06+09:00 2023-10-11T06:23:06+09:00 先週末の三連休、第56回情報科学若手の会に、若手特別講演の枠でありがたくも呼んでいただけたので、参加して発表してきました! 発表で使用したスライドはこちらにおいておきます: ちなみに開催期間中に人々と雑談をしていたら知ってびっくりしたのですが、なんとこの会は1968年7月から続く由緒正しきイベントで、インターネットの父として知られる村井純先生が1955年生まれであることを考えると、驚くほど歴史が長いです。 過去の開催報告も、1996年以降の分については公式ページに存在しており、参加者の名前を見ると、私が大学生の頃に退職された筧捷彦先生が幹事として参加されていたりと、なかなか衝撃的に歴史の長いイ… <p>先週末の三連休、第56回<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%B2%CA%B3%D8">情報科学</a>若手の会に、若手特別講演の枠でありがたくも呼んでいただけたので、参加して発表してきました!</p> <p>発表で使用したスライドはこちらにおいておきます:</p> <iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRD7u8yP166FSu5WVI5HT80IJk918x8Fh4NZePaQWT7hbbTyR4eAYxIBqloeWFrCEH2JmcLOYM1Oqdm/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe> <p>ちなみに開催期間中に人々と雑談をしていたら知ってびっくりしたのですが、なんとこの会は1968年7月から続く由緒正しきイベントで、インターネットの父として知られる<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C2%BC%B0%E6%BD%E3">村井純</a>先生が1955年生まれであることを考えると、驚くほど歴史が長いです。</p> <p>過去の開催報告も、1996年以降の分については公式ページに存在しており、参加者の名前を見ると、私が大学生の頃に退職された<a class="keyword" href="https://d.hatena.ne.jp/keyword/%E4%AA%BE%B9%C9%A7">筧捷彦</a>先生が幹事として参加されていたりと、なかなか衝撃的に歴史の長いイベントに気軽に足を踏み入れてしまったことに開催中に気づいてしまいました。沼ですね…。(いいぞ!)</p> <h1 id="時系列ざっくりまとめ">時系列ざっくりまとめ</h1> <h2 id="準備">準備</h2> <p>ちょうど休みがほしい感じのタイミングだったので、労働からdetachして過ごす日々に、わくわくしながら準備をしていました。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえずね、三連休の間はね、労働のことはすっかり忘れて、軽井沢へ行くよ(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%B2%CA%B3%D8">情報科学</a>若手の会)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710272854787526897?ref_src=twsrc%5Etfw">2023年10月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なお準備ができているとは言っていない(スライドも荷物も、前日の段階では進捗0でした…急いでがんばりました)。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんとか起床して荷物をつめた。これで連休中生き残れる…かな…(なおスライド)(まずは行くことが大事!!!)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710443276153782276?ref_src=twsrc%5Etfw">2023年10月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ちなみにドライヤーがないとしおりに記載されていたので、家からつよいドライヤーを持参しました。 (実際にはふつうの強さのドライヤーはデフォルトで用意されていたので、なくても大丈夫そうでした。来年以降の参考までに。)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あぶない、ドライヤーないのか、持参するぞ…(荷物が増えがち)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710444642809126944?ref_src=twsrc%5Etfw">2023年10月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="初日">初日</h2> <p>新幹線っていう高速回線でhikaliumは転送されました。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%B7%DA%B0%E6%C2%F4%B1%D8">軽井沢駅</a>、到着…誰かいるかな…?<a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a> <a href="https://t.co/EOwm7ktAma">pic.twitter.com/EOwm7ktAma</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710481023396692302?ref_src=twsrc%5Etfw">2023年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>思ったより寒く、猛暑の夏から冬の始まりに急に飛ばされたような感じでした。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">軽井沢、さむい!!!!夜大丈夫かな…(風邪ひいたりしそう)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710497025488470427?ref_src=twsrc%5Etfw">2023年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして、問題はここから研修施設までの移動をどうするか。まあなんとかなるでしょ、の精神で来つつ、どうやら知り合いが車でくるらしいという情報を聞き、便乗させてもらおうと思っていたところ、なんと渋滞で大幅に遅れそうになっていたとのこと。そうか秋の三連休ですものね、皆様も旅をしたいと思っていらっしゃるのでしょう。仕方ありませんわ…(三連休開催のつらいところ)。</p> <p>なので、同じく交通手段獲得<a class="keyword" href="https://d.hatena.ne.jp/keyword/RTA">RTA</a>を走っていた参加者のお二人とエンカウントして、タクシーで現地へと向かうことにしました。</p> <p>(ちょうどここで<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%B7%D7%BB%BB%B5%A1">量子計算機</a>関連の雑談ができて楽しかったです。)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">多少遅刻しつつ <a href="https://twitter.com/_yyu_?ref_src=twsrc%5Etfw">@_yyu_</a> <a href="https://twitter.com/nkowne63?ref_src=twsrc%5Etfw">@nkowne63</a> さんとタクシー同乗させてもらって到着…(本日のタスク、終了!!)<br><br> <a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710523749051892059?ref_src=twsrc%5Etfw">2023年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>若干遅刻しつつ参加したところ、「ブログを書くまでが #wakate2023」という、どこかで聞いたようなフレーズが耳に入ってきました。ということで、このブログを書いているわけです。(振り返り、大事なのでね!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ブログを書くまでが <a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a> (どこかで聞いたようなフレーズだな…)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710523870808355233?ref_src=twsrc%5Etfw">2023年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>初日の講演は</p> <ul> <li>GoでORMを自作する</li> <li>スポンサーセッション : PFNを支えるストレージシステム</li> <li>招待講演 : 実用水準の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DF%A5%F3%A5%B0%B8%C0%B8%EC">プログラミング言語</a>を個人規模でつくる</li> </ul> <p>の三本立てとなっていました。</p> <p>特に3つ目の、SATySFiの作者gfnさんによる講演は、首を縦に無限回振りたくなるほど、何かを自作する際に発生しがちな感情や思考の機微を的確に説明する講演で非常にためになりました。</p> <p>ちなみにgfnさんとは帰りのタクシーで一緒になったため、フォントやPDF周りの闇についてわいわい盛り上がることができました。Type 1 fonts は闇が深い、覚えた!</p> <p>夜は、人々で親睦を深めるために <a href="https://estimathon.com/">Estimathon</a>という数字予想ゲームが開催され、非常に盛り上がりました。 まず、ルールを理解するところ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>て「結果が小さくなるほうが得点が高い」という部分が、普段の思考のバイアス(大きい方が得点が高い)に引っ張られて頭がぐるぐるしましたし、その後も、どの程度のレンジで値を特定すればいいのかの戦略など、単なる<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D5%A5%A7%A5%EB%A5%DF%BF%E4%C4%EA">フェルミ推定</a>的な予想を超えた面白さが満載で、めっちゃ楽しかったです。これ、会社の人々とかと、またやりたいなあと思いました。</p> <p>なお、我々のチームは頭のネジが外れていたので、途中で結果が爆発的に大きくなってしまい、スコアボードに数値ではなく「とても大きい」と書かれるなどの実績を解除してしまいました…(でも楽しかった!!)</p> <p>そのあとは、各自が持ち寄った大量のお菓子を囲みながら、人々とわいわい喋りつつ、私はスライド作成<a class="keyword" href="https://d.hatena.ne.jp/keyword/RTA">RTA</a>をしていました…。</p> <p>あと、次の日のLT大会に向けて準備していたmomokaさんの検証を手伝っていたら、なんか平日に見慣れた画面に突入してしまい労働の波動を感じるなどしてしまいました(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a>だからへーきへーき!!これは仕事じゃないもんね!!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">期間中は仕事のこと忘れるぞ!と思っていたのに、結局<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromium">Chromium</a> CodeSearchとGerritを目にしてしまうことになる深夜をやっていた(仕事じゃないのでOK)<br><br> <a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1710815843339362757?ref_src=twsrc%5Etfw">2023年10月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1 id="二日目">二日目</h1> <p>早起きして朝食を食べる超健康生活(なお午前3時までスライド作成やパケットキャプチャをしていた模様)をはじめつつ、本題の講演二日目が始まりました。</p> <p>「Wasmを実行するunikernelとWasm<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>の開発」という発表でsaza_kuさんとainnoさんが提案していたエコシステムは、確かに上手く行けばめっちゃ熱い話だな…というか我々なんとかOSもこういう方向に進むべきなのでは!?!?という示唆を得られる、とてもわかりやすくためになる発表でした。これからの成果を楽しみにしています!</p> <iframe class="speakerdeck-iframe" frameborder="0" src="https://speakerdeck.com/player/bc721c2c400b48dbb9352efb82fff248" title="第56回 情報科学若手の会 Wasmを実行するunikernelとWasmコンパイラ" allowfullscreen="true" style="border: 0px; background: padding-box padding-box rgba(0, 0, 0, 0.1); margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 100%; height: auto; aspect-ratio: 560 / 315;" data-ratio="1.7777777777777777"></iframe> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%B7%D7%BB%BB%B5%A1">量子計算機</a>関連の講演も複数あり、まさに冒頭の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%B7%DA%B0%E6%C2%F4%B1%D8">軽井沢駅</a>から研修所までの道<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A4%CE%A4%EA%A4%F2">のりを</a>共にしたお二人がそれぞれ発表した内容は、どちらも量子計算の基礎をわかりやすく説明してくれていて、とてもためになりました。</p> <p>あと、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF">量子コンピュータ</a>ーの世界におけるOSはどのようなものになるのか、ということについてもお二人とお話できて、将来考えてみる価値のある面白いテーマかもしれないな、と感じました。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF">量子コンピュータ</a>ー関連の話を聞いて、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF">量子コンピュータ</a>ーにおけるOSの立場を考えたら楽しそうな気がしてきた(色々勉強になることが聞けて私も楽しかったです!!!)<a href="https://twitter.com/hashtag/wakate2023?src=hash&amp;ref_src=twsrc%5Etfw">#wakate2023</a> <a href="https://t.co/vN1AMsbp5j">https://t.co/vN1AMsbp5j</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1711232189357342912?ref_src=twsrc%5Etfw">2023年10月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>また、海外では<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF">量子コンピュータ</a>ーを自作した人々がいる、という話もあったりと、自作欲をかきたてられるお話も色々と聞くことができました。私も元々<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%B7%D7%BB%BB%B5%A1">量子計算機</a>には少し興味があって、ある程度の知識は本から摂取していたので、それに加えて実際に専門として取り組まれている人々の話を聞くことができたのは、非常に楽しかったです。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「<a class="keyword" href="https://d.hatena.ne.jp/keyword/%CE%CC%BB%D2%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF">量子コンピュータ</a>を家庭で持つためにまず真空中に原子を一つ固定する装置を自作します」と言ったときの反応が一番良かった。accustomed</p>&mdash; ノーン (@nkowne63) <a href="https://twitter.com/nkowne63/status/1711198254292218004?ref_src=twsrc%5Etfw">2023年10月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そのあとは、私の発表ターンに続き、様々な面白いトピックでの発表が続きました。研究発表的な内容も、ざっくりと概観するような内容も、どちらも摂取できるのが、この会の良いところだなあ、と感じました。</p> <p>また、そのあとのLTでも、面白い話がたくさんあったのですが、まだ未公開な話も多くあったので、とにかく楽しかったということだけを記しておくことにします。興味がある皆さんは、ぜひ次回の<a class="keyword" href="https://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%B2%CA%B3%D8">情報科学</a>若手の会に参加を検討されてみてはいかがでしょうか!!!!!!!</p> <h1 id="そのほかのメモ">そのほかのメモ</h1> <p>参加者のひとり、asu_paraさんの<a href="https://zenn.dev/ultrasupara/articles/9287d0681121cb">参加記事</a>に</p> <blockquote><p>hikaliumさんはセキュキャンなどを通してOSとか低レイヤーの人ということで知っていますし、講演もその通りに沿ったものです。ぼく個人としては、自身は概念のようなものと宣言されているにも関わらず、人間的な一面が見られるpostが多いのが趣深い人やなといつも思って、見てます。</p></blockquote> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">それな、人間の記憶って<a class="keyword" href="https://d.hatena.ne.jp/keyword/DRAM">DRAM</a>より飛びやすいらしいし、全く困ったものです(まるで他人事のように)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1612101076962144260?ref_src=twsrc%5Etfw">2023年1月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>と書かれていて、分かるな〜、となっています(まるで他人事のように2)</p> <p>あとは、低レイヤと高レイヤの話についての視聴者の反応(めっちゃわかる)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">高レイヤが低レイヤにかてないの、精神が不調のときにかなり痛感したな。(頭と精神)</p>&mdash; ノーン (@nkowne63) <a href="https://twitter.com/nkowne63/status/1710915898662682648?ref_src=twsrc%5Etfw">2023年10月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>他にも、同室の人々が私も含め、みんな引きこもりコンピューター大好きオタクムーブを発動していて面白かったです。(この界隈、性別の偏りが激しいので、相部屋(ひとり)になりがちの人々が久々に修学旅行的な雰囲気の部屋に放り込まれて、結果みんなおふとんの上で座り込んでパソコンカタカタする夜、みたいになっていて最高でした。)momokaさんのあやしいパケット検証を手伝ったり、ainnoさんのRustコードをレビューする会をしたり、たまにはこういうのも楽しいなあ!と感じました。</p> <p>ちなみに:フィードバックに書き忘れたのですが、女子部屋が最も交通量の多い場所に配置されていたので、もしかすると交通量が少ない廊下の奥の方の部屋のほうがよいのではないか、という話が挙がっていました。来年以降の運営の参考になれば…。</p> <p>あとは、狭い界隈の人々と物理世界で会えたのがよかったですね。大学の研究室の後輩から「先生が、たまには研究室に顔を出せって言ってましたよ!」と言われたりとか(なおその方はNVDIMMをやろうとしていたところ、Optaneがおしまいになったのでおじゃんになったらしい、かなしいね)、私が行こうと思っていた大学院の研究室に行く予定の学生の方とか(品川先生〜)、セキュキャンつながりの人々とか、とにかく、たくさんの方々と話すことができて、とても楽しかったです。</p> <h1 id="まとめ">まとめ</h1> <p>久々のイベント登壇でしたが、面白いことをしているたくさんの方々と会って話せるお泊りイベントはとても楽しかったです。たまには日常を忘れて、こういうイベントに参加するのも、よいアイディアを得たり、今後の道筋を立てる助けになるような気がしました。また来年も参加したいなあ、という気持ちにさせてくれる、快適なイベントを運営してくださった、幹事の皆さまと、参加者のみなさま、ありがとうございました!またどこかでお会いしましょう〜!!</p> hikalium CPUを自作したりコンピューターアーキテクチャを理解するためにおすすめの本の一覧 hatenablog://entry/820878482969230330 2023-09-21T00:13:58+09:00 2023-09-21T01:18:35+09:00 hikaliumの独断と偏見で、積読は除いている。最近も結構新しい本が色々出ているので、それもいいかもしれないが、ある程度評価の定まった本を探したい場合に参考になれば。 ちなみに、hikaliumがセキュキャンでCPU自作を教えていたときのコードはここにある。参考にならないかもしれないが、おまけにどうぞ。 github.com ディジタル回路設計とコンピュータアーキテクチャ 無印(MIPS版) ARM版 RISC-V版 ハードウエア記述言語で実際にCPUをつくりながら、各アーキテクチャについても学べる良書。 MIPS版が広く知られているが、ARM版、RISC-V版も登場している。無印版はよくあ… <p>hikaliumの独断と偏見で、<a class="keyword" href="https://d.hatena.ne.jp/keyword/%C0%D1%C6%C9">積読</a>は除いている。最近も結構新しい本が色々出ているので、それもいいかもしれないが、ある程度評価の定まった本を探したい場合に参考になれば。</p> <p>ちなみに、hikaliumがセキュキャンでCPU自作を教えていたときのコードはここにある。参考にならないかもしれないが、おまけにどうぞ。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fosecpu%2F" title="osecpu" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/osecpu/">github.com</a></cite></p> <h2 id="ディジタル回路設計とコンピュータアーキテクチャ">ディジタル回路設計とコンピュータ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a></h2> <ul> <li><a href="https://amzn.asia/d/hyaIv5C">無印(MIPS版)</a></li> <li><a href="https://amzn.asia/d/ixtCN2i">ARM版</a></li> <li><a href="https://amzn.asia/d/75SLozs">RISC-V版</a></li> </ul> <p>ハードウエア記述言語で実際にCPUをつくりながら、各<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>についても学べる良書。</p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/MIPS">MIPS</a>版が広く知られているが、ARM版、<a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-V版も登場している。無印版はよくある技術書サイズだが、ARMと<a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-V版は大型本なので、そこらへんの好みとかも勘案するとよいかもしれない。</p> <h2 id="CPUの創り方">CPUの創り方</h2> <ul> <li><a href="https://amzn.asia/d/1gKfJOq">Amazon</a></li> </ul> <p>表紙が<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%E1%A5%A4%A5%C9%A4%B5%A4%F3">メイドさん</a>だが、侮ることなかれ。(と私は中学生の時にクラスの人々の前で言いました。)</p> <p>電子工作初心者の人々にもわかりやすく、回路素子の基本的な扱い方や、データシートの読み方も教えてくれる、実装寄りの良書。</p> <p>74HCシリーズのICが手に入りにくいという現代的な事情はあるが、等価な回路を上の本などを参考にしつつ<a class="keyword" href="https://d.hatena.ne.jp/keyword/Verilog">Verilog</a>-HDLで記述したりすれば、<a class="keyword" href="https://d.hatena.ne.jp/keyword/FPGA">FPGA</a>ボードひとつでも等価なものを十分につくることができる。</p> <h2 id="RISC-V原典-オープンアーキテクチャのススメ"><a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-V原典 オープン<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>のススメ</h2> <ul> <li><a href="https://amzn.asia/d/gLTt8BE">Amazon</a></li> </ul> <p>きれいな<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>で知られる<a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-Vの設計思想の背景や、どうしてその設計が選択されたのか、という思考の背後を知ることができる本。もう少し高いレベルからCPUのことを知りたかったり、<a class="keyword" href="https://d.hatena.ne.jp/keyword/RISC">RISC</a>-Vについて知りたい場合には役立つ。</p> <h2 id="コンピュータアーキテクチャ-定量的アプローチ">コンピュータ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/%C4%EA%CE%CC">定量</a>的アプローチ</h2> <ul> <li><a href="https://amzn.asia/d/2XjIx3N">Amazon</a></li> </ul> <p>通称ヘネパタ。大学でこの本を参考にキャッシュの特性を調べるグラフを描画する課題が出て、面白いなあと思った記憶がある。</p> <p>めちゃくちゃ教科書的な内容なので、読むのは大変だし最初から最後まで読むタイプの本ではないが、持っておいて損はない。ペラペラめくったり目次をみて、興味のあるところや、参考になりそうなところを読む、辞書的な使い方をするのがよい。</p> <h2 id="作りながら学ぶコンピュータアーキテクチャ">作りながら学ぶコンピュータ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a></h2> <ul> <li><a href="https://amzn.asia/d/cncA9eR">Amazon</a></li> </ul> <p>上の方の本の翻訳にも携わっておられる、天野先生の著書。他の本では忘れられがちな、割り込み処理の実装方法が記述されているとネットで聞いて自分も購入した。</p> <p>絶版本なので手に入れるのは少し大変。図書館などにあるかどうか、確認してみるのも手かもしれない。</p> <p>上の分厚い辞書みたいな本たちにくらべたら、薄くて読みやすそうな見た目をしているので、一見の価値はある。</p> <h2 id="FPGAの原理と構成"><a class="keyword" href="https://d.hatena.ne.jp/keyword/FPGA">FPGA</a>の原理と構成</h2> <ul> <li><a href="https://amzn.asia/d/f9vQNaA">Amazon</a></li> </ul> <p>いま気づいたがこれも天野先生の著書じゃん。おそらくCPU自作をはじめる最も手軽な方法は<a class="keyword" href="https://d.hatena.ne.jp/keyword/FPGA">FPGA</a>を用いることだが、じゃあ<a class="keyword" href="https://d.hatena.ne.jp/keyword/FPGA">FPGA</a>って一体どうやって動いているの?というところの疑問を解決してくれる本。これも小さめ技術書によくあるサイズ感なので、電車の中でも読みやすいのでおすすめ。</p> hikalium Chromebookの開発者モードへの遷移をちょっと追う hatenablog://entry/820878482953042253 2023-07-27T00:08:57+09:00 2023-07-27T00:14:49+09:00 某ブログに触発されて、公開情報からChromiumOSの気になるところを追う軽い記事でも書こうかなという気持ちに急になったので書いていく。正確さも何も保証しないし、公開情報しか載っていないのであしからず。公開情報であることを示すために出典へのリンクをいっぱい張ります。 Chromebookには開発者モードというunsecureなモードがあって、これを使うと自作OSをブートさせたり色々できて楽しい。それに入るためには、リカバリモードに入ってCtrl-Dを押してEnterを押すという作業が通常必要なわけだが、これで何が起きるのかちょっと追いかけてみよう。 まず、ChromebookはBIOSでもU… <p><a href="https://hackmd.io/@elkurin/BkpclhzOh">某ブログ</a>に触発されて、公開情報からChromiumOSの気になるところを追う軽い記事でも書こうかなという気持ちに急になったので書いていく。正確さも何も保証しないし、公開情報しか載っていないのであしからず。公開情報であることを示すために出典へのリンクをいっぱい張ります。</p> <p><a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>には開発者モードというunsecureなモードがあって、これを使うと自作OSをブートさせたり色々できて楽しい。それに入るためには、<a href="https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md">リカバリモードに入ってCtrl-Dを押してEnterを押すという作業が通常必要</a>なわけだが、これで何が起きるのかちょっと追いかけてみよう。</p> <p>まず、<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>は<a class="keyword" href="https://d.hatena.ne.jp/keyword/BIOS">BIOS</a>でも<a class="keyword" href="https://d.hatena.ne.jp/keyword/UEFI">UEFI</a>でもないファームウエアを採用している。(一部例外はある。)これはverified bootとかvbootとか呼ばれていて、このあたりに<a href="https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery/#boot-flowchart">いい感じの図</a>がある。情報が最新の状態に更新されているかは謎だが…(斜め上に視線を動かす)</p> <p>あと、<a href="https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices/custom-firmware/">ここのページ</a>にファームウエアまわりの情報が載っていて、こんなかっこいい一文が書いてある。</p> <blockquote><p>The <a class="keyword" href="https://d.hatena.ne.jp/keyword/Chrome%20OS">Chrome OS</a> <a class="keyword" href="https://d.hatena.ne.jp/keyword/firmware">firmware</a> is always verified as signed by <a class="keyword" href="https://d.hatena.ne.jp/keyword/Google">Google</a></p></blockquote> <p>いいはなし。Root of Trustってやつだね。</p> <p>さて、このページの下の方に、H2C (<a class="keyword" href="https://d.hatena.ne.jp/keyword/UEFI">UEFI</a>-based), U-boot, <a class="keyword" href="https://d.hatena.ne.jp/keyword/Coreboot">Coreboot</a>, と<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>で使われていた歴代ファームウエアの名前が並び、それに続いて<a href="https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices/custom-firmware/#depthcharge">depthcharge</a>ってやつが新し目の<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>だと使われているぞ!と書いてある。へえ〜!</p> <p>そこから<a href="https://www.chromium.org/chromium-os/2014-firmware-summit/ChromeOS%20firmware%20summit%20-%20Depthcharge.pdf">こんなスライド</a>へもリンクが飛んでいるが、なんと2014年である。まあつまるところ、多分近頃の<a class="keyword" href="https://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>はみんなdepthchargeを使ってるんじゃないかな?(適当)</p> <p>さて、そんなわけで、depthchargeのコードは<a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/">ここ</a>にあるわけだが、まずREADMEがない。なるほど…?</p> <p>ちなみに"depthcharge chromiumos"で<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%B0%A5%B0%A4%EB">ググる</a>と<a href="https://chromium.googlesource.com/chromiumos/platform/depthcharge/">無機質なGitilesというシステムのページ</a>に飛ばされるが、ここは検索機能とかがないので、便利な<a href="https://source.chromium.org/chromiumos">Chromium Code Search</a>を使おう!超便利だよ!(いつもお世話になっているので頭が上がらない)</p> <p>さて本題に戻って、とりあえずdepthcharge配下で"recovery"とかの単語で調べると、src/platform/depthcharge/src/vboot/ui.hというファイルがヒットする。</p> <pre class="code" data-lang="" data-unlink>/* Screens. */ enum ui_screen { /* Wait screen for EC sync and AUXFW sync */ UI_SCREEN_FIRMWARE_SYNC = 0x100, /* Broken screen */ UI_SCREEN_RECOVERY_BROKEN = 0x110, /* Advanced options */ UI_SCREEN_ADVANCED_OPTIONS = 0x120, /* Language selection screen */ UI_SCREEN_LANGUAGE_SELECT = 0x130, /* Debug info */ UI_SCREEN_DEBUG_INFO = 0x140, /* Firmware log */ UI_SCREEN_FIRMWARE_LOG = 0x150, /* First recovery screen to select recovering from disk or phone */ UI_SCREEN_RECOVERY_SELECT = 0x200, /* Invalid recovery media inserted */ UI_SCREEN_RECOVERY_INVALID = 0x201, /* Confirm transition to developer mode */ UI_SCREEN_RECOVERY_TO_DEV = 0x202, /* Recovery using phone */ UI_SCREEN_RECOVERY_PHONE_STEP1 = 0x210, UI_SCREEN_RECOVERY_PHONE_STEP2 = 0x211, /* Recovery using disk */ UI_SCREEN_RECOVERY_DISK_STEP1 = 0x220, UI_SCREEN_RECOVERY_DISK_STEP2 = 0x221, UI_SCREEN_RECOVERY_DISK_STEP3 = 0x222, /* Developer mode screen */ UI_SCREEN_DEVELOPER_MODE = 0x300,</pre> <p><a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui.h;l=198-226;drc=3eda3d7bd3195f6d8ff59954e6b2967e42201bcb">https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui.h;l=198-226;drc=3eda3d7bd3195f6d8ff59954e6b2967e42201bcb</a></p> <p><code>UI_SCREEN_RECOVERY_TO_DEV</code>とか、いかにもそれっぽい名前なので、今度はそれで検索すると、src/platform/depthcharge/src/vboot/ui.cというファイルが見つかる。まさに特定のキーを押したときに画面遷移するコードが書いてある!</p> <pre class="code" data-lang="" data-unlink> /* Manual recovery keyboard shortcuts */ if (ui-&gt;key == UI_KEY_REC_TO_DEV || (CONFIG(DETACHABLE) &amp;&amp; ui-&gt;key == UI_BUTTON_VOL_UP_DOWN_COMBO_PRESS)) { return ui_screen_change(ui, UI_SCREEN_RECOVERY_TO_DEV); }</pre> <p><a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui.c;l=39-44;drc=fcfa6efb8f221877e771a7bc382267a3ebcdee48">https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui.c;l=39-44;drc=fcfa6efb8f221877e771a7bc382267a3ebcdee48</a></p> <p>ちなみにここに書いてあるとおり、キーボードが外れるタイプのデ<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>(DETACHABLE)だと、音量キーの同時押しでdevmodeに入れることがわかる。(もちろん<a href="https://chromium.googlesource.com/chromiumos/docs/+/HEAD/debug_buttons.md#firmware-menu-interface">ドキュメント</a>に書いてあるよ!)</p> <p>さて、じゃあこの画面の遷移した先を見に行こう。</p> <p>src/platform/depthcharge/src/vboot/ui/screens.c</p> <pre class="code" data-lang="" data-unlink>static vb2_error_t recovery_to_dev_init(struct ui_context *ui) { if (ui-&gt;ctx-&gt;flags &amp; VB2_CONTEXT_DEVELOPER_MODE) { /* Notify the user that they are already in dev mode */ UI_WARN(&#34;Already in dev mode\n&#34;); return set_ui_error_and_go_back( ui, UI_ERROR_DEV_MODE_ALREADY_ENABLED); } if (!CONFIG(PHYSICAL_PRESENCE_KEYBOARD) &amp;&amp; ui_is_physical_presence_pressed()) { UI_INFO(&#34;Physical presence button stuck?\n&#34;); return ui_screen_back(ui); } if (CONFIG(PHYSICAL_PRESENCE_KEYBOARD)) { ui-&gt;state-&gt;selected_item = RECOVERY_TO_DEV_ITEM_CONFIRM; } else { /* * Disable &#34;Confirm&#34; button for other physical presence types. */ UI_SET_BIT(ui-&gt;state-&gt;hidden_item_mask, RECOVERY_TO_DEV_ITEM_CONFIRM); ui-&gt;state-&gt;selected_item = RECOVERY_TO_DEV_ITEM_CANCEL; } ui-&gt;physical_presence_button_pressed = 0; return VB2_SUCCESS; } static vb2_error_t recovery_to_dev_finalize(struct ui_context *ui) { UI_INFO(&#34;Physical presence confirmed!\n&#34;); /* Validity check, should never happen. */ if (ui-&gt;state-&gt;screen-&gt;id != UI_SCREEN_RECOVERY_TO_DEV || (ui-&gt;ctx-&gt;flags &amp; VB2_CONTEXT_DEVELOPER_MODE) || ui-&gt;ctx-&gt;boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) { UI_ERROR(&#34;ERROR: Dev transition validity check failed\n&#34;); return VB2_SUCCESS; } UI_INFO(&#34;Enabling dev mode and rebooting...\n&#34;); if (vb2api_enable_developer_mode(ui-&gt;ctx) != VB2_SUCCESS) { UI_WARN(&#34;Failed to enable developer mode\n&#34;); return VB2_SUCCESS; } return VB2_REQUEST_REBOOT_EC_TO_RO; }</pre> <p><a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui/screens.c;l=799-851;drc=85f76f13f623d3e4e3a01224a381abf755f1c1bb">https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/depthcharge/src/vboot/ui/screens.c;l=799-851;drc=85f76f13f623d3e4e3a01224a381abf755f1c1bb</a></p> <p>vb2api_enable_developer_mode()ってやつがあやしいね!そして、それを呼んだあとは再起動してるみたい。depthchargeの中にはtest用のmockしかなかったので、ひとつ上のsrc/platformで検索をかけると、vboot_referenceで実装が見つかった。</p> <pre class="code" data-lang="" data-unlink>vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx) { if (ctx-&gt;boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) { VB2_DEBUG(&#34;ERROR: Can only enable developer mode from manual &#34; &#34;recovery mode\n&#34;); return VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED; } uint32_t flags; VB2_DEBUG(&#34;Enabling developer mode...\n&#34;); flags = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS); flags |= VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE; vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS, flags); VB2_DEBUG(&#34;Mode change will take effect on next reboot\n&#34;); return VB2_SUCCESS; }</pre> <p><a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/vboot_reference/firmware/2lib/2misc.c;l=433-452;drc=def2f5af7ac03eac3a4a79795275f1cf6cd7f827">https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/vboot_reference/firmware/2lib/2misc.c;l=433-452;drc=def2f5af7ac03eac3a4a79795275f1cf6cd7f827</a></p> <p>VB2_SECDATA_<a class="keyword" href="https://d.hatena.ne.jp/keyword/FIRMWARE">FIRMWARE</a>_FLAG_DEV_MODE ってフラグがセットされるんだね〜</p> <p>ということでこいつを調べると、フラグの定義も見つかった。</p> <pre class="code" data-lang="" data-unlink>/* Flags for firmware space */ enum vb2_secdata_firmware_flags { /* * Last boot was developer mode. TPM ownership is cleared when * transitioning to/from developer mode. Set/cleared by * vb2_check_dev_switch(). */ VB2_SECDATA_FIRMWARE_FLAG_LAST_BOOT_DEVELOPER = (1 &lt;&lt; 0), /* * Virtual developer mode switch is on. Set/cleared by the * keyboard-controlled dev screens in recovery mode. Cleared by * vb2_check_dev_switch(). */ VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE = (1 &lt;&lt; 1), };</pre> <p><a href="https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/vboot_reference/firmware/2lib/include/2secdata.h;l=25-40;drc=6a33a0fca3e4f5cd9c3b3fd4ac0b5b8c7ffc018e">https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/vboot_reference/firmware/2lib/include/2secdata.h;l=25-40;drc=6a33a0fca3e4f5cd9c3b3fd4ac0b5b8c7ffc018e</a></p> <p>コメントいわく、最後の起動時の状態も記録しておいて、もしnormalからdevに遷移していたら、<a class="keyword" href="https://d.hatena.ne.jp/keyword/TPM">TPM</a>のownershipをクリアするって書いてあるね!まあ要するに、normalのときに保存されたユーザーの秘密情報がもれないように、なんでもありのdevmodeに遷移するときはデータを消し飛ばすってことなんでしょう。(実際devmodeに移行するとなんかの消去が走っている画面になる。)</p> <p>次回はその消去の画面のところを見に行きましょう!(<a class="keyword" href="https://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a>部分であることを祈りましょう…)</p> <p>おやすみなさい!</p> hikalium VRM as a Code - またはコードによりあなたのアバターを定義する方法について hatenablog://entry/4207112889950166206 2023-01-09T16:14:29+09:00 2023-01-09T16:14:29+09:00 下書きのまましばらく放置されたのでインターネットの海に放流 目標 hikaliumのアバターをコードで定義して、GUIを用いることなく服を着せ替えたりパラメーターを操作するなどできるようにしたい 先行研究 VRM Add-on for Blender BlenderにVRM関連の機能を追加するプラグインの実装 背景情報 VRM形式 人型アバターで最近主流になりつつあるファイルフォーマット。glTF形式をベースにしている。 公式ページ: https://vrm.dev/ サンプルデータ: https://github.com/vrm-c/vrm-specification/tree/master… <p>下書きのまましばらく放置されたのでインターネットの海に放流</p> <h1 id="目標">目標</h1> <p>hikaliumの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>をコードで定義して、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>を用いることなく服を着せ替えたりパラメーターを操作するなどできるようにしたい</p> <h1 id="先行研究">先行研究</h1> <ul> <li><a href="https://github.com/saturday06/VRM_Addon_for_Blender">VRM Add-on for Blender</a> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>に<a class="keyword" href="http://d.hatena.ne.jp/keyword/VRM">VRM</a>関連の機能を追加する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3">プラグイン</a>の実装</li> </ul> </li> </ul> <h1 id="背景情報">背景情報</h1> <h2 id="VRM形式"><a class="keyword" href="http://d.hatena.ne.jp/keyword/VRM">VRM</a>形式</h2> <p>人型<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>で最近主流になりつつあるファイルフォーマット。glTF形式をベースにしている。</p> <ul> <li>公式ページ: <a href="https://vrm.dev/">https://vrm.dev/</a></li> <li>サンプルデータ: <a href="https://github.com/vrm-c/vrm-specification/tree/master/samples">https://github.com/vrm-c/vrm-specification/tree/master/samples</a></li> </ul> <h2 id="glTF形式">glTF形式</h2> <ul> <li>仕様書: <a href="https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html">https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html</a></li> <li>fadisさんによる解説: <a href="https://fadis.booth.pm/items/2366496">https://fadis.booth.pm/items/2366496</a></li> </ul> <h1 id="調査">調査</h1> <h2 id="VRMglTFを理解する"><a class="keyword" href="http://d.hatena.ne.jp/keyword/VRM">VRM</a>/glTFを理解する</h2> <h3 id="bin領域のデータのエンディアン">bin領域のデータの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%C7%A5%A3%A5%A2%A5%F3">エンディアン</a></h3> <p>Little <a class="keyword" href="http://d.hatena.ne.jp/keyword/Endian">Endian</a>にしなければならない(MUST)</p> <ul> <li><a href="https://github.com/KhronosGroup/glTF/commit/5673994f6f7254a11938ba13eff52667c7a4f3f4">https://github.com/KhronosGroup/glTF/commit/5673994f6f7254a11938ba13eff52667c7a4f3f4</a></li> <li><a href="https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#buffers-and-buffer-views-overview">https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#buffers-and-buffer-views-overview</a></li> </ul> <blockquote><p>All buffer data defined in this specification (i.e., geometry attributes, geometry indices, sparse accessor data, animation inputs and outputs, inverse bind matrices) MUST use little <a class="keyword" href="http://d.hatena.ne.jp/keyword/endian">endian</a> byte order.</p></blockquote> <h3 id="UV-map">UV map</h3> <p><a href="https://docs.blender.org/manual/ja/dev/addons/import_export/scene_gltf2.html#uv-mapping">https://docs.blender.org/manual/ja/dev/addons/import_export/scene_gltf2.html#uv-mapping</a></p> <p>KHR_texture_transform</p> <h3 id="Animation">Animation</h3> <p><a href="https://pixiv.github.io/three-vrm/packages/three-vrm/examples/">three-vrm example</a> の humanoidAnimation のデモが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>に使えそう</p> <h1 id="実装">実装</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhikalium%2Fvacation" title="GitHub - hikalium/vacation: VRM as a Code application" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/hikalium/vacation">github.com</a></cite></p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ああああああああ動いたあああ!!!!(primitiveのattributeにTexCoords(0)を追加し忘れるというただの凡ミスだった…最小ケースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>大事) <a href="https://t.co/eINOocaSVU">pic.twitter.com/eINOocaSVU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1610485836059119622?ref_src=twsrc%5Etfw">2023年1月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>とりあえず<a class="keyword" href="http://d.hatena.ne.jp/keyword/VRM">VRM</a>をglTFとして読み込んだら、テクスチャ付きでprimitive単位に分割して再出力することはできた。</p> <p>また気力が湧いたら続きをやろう。</p> hikalium 2022年の振り返り hatenablog://entry/4207112889949761411 2022-12-31T14:39:45+09:00 2022-12-31T14:39:45+09:00 例年通り、今年あったことの概要をまとめておく。 1月 3Dプリンターをお買い上げしてた(今年だったんだ…) 思い立ったらすぐ行動、ってね pic.twitter.com/1HGk34pGf9— hikalium (@hikalium) 2022年1月4日 ちなみにブログ記事も書いた hikalium.hatenablog.jp 2月 3Dプリンタでメンガーのスポンジを印刷してた(筆記用具は商品には含まれません) まあ筆立てとして使えないこともない(?) pic.twitter.com/pg5tzHYnGn— hikalium (@hikalium) 2022年2月5日 そしてhikaliumと… <p>例年通り、今年あったことの概要をまとめておく。</p> <h2 id="1月">1月</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>をお買い上げしてた(今年だったんだ…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">思い立ったらすぐ行動、ってね <a href="https://t.co/1HGk34pGf9">pic.twitter.com/1HGk34pGf9</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1478236964512223236?ref_src=twsrc%5Etfw">2022年1月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ちなみにブログ記事も書いた</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2022%2F01%2F05%2F230059" title="光造形3Dプリンターはじめてみた(ELEGOO Mars 2 Pro) - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2022/01/05/230059">hikalium.hatenablog.jp</a></cite></p> <h2 id="2月">2月</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E1%A5%F3%A5%AC%A1%BC">メンガー</a>のスポンジを印刷してた(筆記用具は商品には含まれません)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">まあ筆立てとして使えないこともない(?) <a href="https://t.co/pg5tzHYnGn">pic.twitter.com/pg5tzHYnGn</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1489956821502611458?ref_src=twsrc%5Etfw">2022年2月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてhikaliumとして初の社のイベント登壇をした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">✅実績解除: 社の開催するイベントで仮想世界の住人として参加した <a href="https://t.co/NWw77oxDEj">pic.twitter.com/NWw77oxDEj</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1491360840716480513?ref_src=twsrc%5Etfw">2022年2月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてもう一台<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>が増えた(錯乱)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いや、<a class="keyword" href="http://d.hatena.ne.jp/keyword/SLA">SLA</a>方式で満足したなら次はFDM方式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>も試すべきでしょ、ということでこうなった(我々はどこへ向かっているのか、何をしようとしているのか) <a href="https://t.co/hpepx69q7i">pic.twitter.com/hpepx69q7i</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1493924383290982400?ref_src=twsrc%5Etfw">2022年2月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>戦争とかが始まったのもこのあたりらしい(世も末ですな)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">インターネット越しに情報がどんどん入ってくるの、面白い一方で、いったい目に入ってくる情報の何%がリアルワールドの現実に即してない情報なのか、想いを馳せている(きっとこの領域でも戦いは発生しているのでね)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1496694239472025600?ref_src=twsrc%5Etfw">2022年2月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あまりにも眠れなさすぎる現状を歌にするなどした(かっとしてつい…聴かなくていいですよ!!!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">また謎のうたを作ってしまった…<br>睡眠とスケジューリングが苦手なOSのみなさんにおすすめです(?)<br><br>すいみんpreparation - hikalium <a href="https://t.co/SXSIy15DZd">https://t.co/SXSIy15DZd</a> <a href="https://t.co/uRz2IXrNfE">pic.twitter.com/uRz2IXrNfE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1497171371431923715?ref_src=twsrc%5Etfw">2022年2月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="3月">3月</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%BD%E8%CD%FD%B3%D8%B2%F1">情報処理学会</a>のOS研究会で社の仮想ブースを回すなどしていた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日は結局これにほぼ一日を費やしてしまったが、久々にカンファレンスに行ったとき/出展したときのあの感じを味わえて懐かしさを感じた。話を聞きに来てくれた皆様、ありがとうございました!<br>(なお体力の残量はゼロです。消費電力の最適化が必要です…。) <a href="https://t.co/s8RNmHzhFo">https://t.co/s8RNmHzhFo</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1503325260497637378?ref_src=twsrc%5Etfw">2022年3月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>新しいお友達もお迎え(コアスイッチとして現在も頑張ってくれています)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">あたらしいおともだち!<br>(自作するかーとか言ってたのに吊るしのスイッチを買ってしまった…) <a href="https://t.co/0churVEJwI">pic.twitter.com/0churVEJwI</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1505048453822386177?ref_src=twsrc%5Etfw">2022年3月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>おうち<a class="keyword" href="http://d.hatena.ne.jp/keyword/NOC">NOC</a>業の様子</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">仕上がってきた(なぜ私の休日はいつもこういうことに時間が消えてしまうのか(楽しいからだよ仕方ないね…)) <a href="https://t.co/XpwoEkqKs9">pic.twitter.com/XpwoEkqKs9</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1505803395323817987?ref_src=twsrc%5Etfw">2022年3月21日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>車輪を再発明した(車輪ではなく車(輪がついた物体の進入を防ぐ)輪)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">これでブラーバとかルンバが円環の理に閉じ込められずに済むってわけですよ(かなりの確率でここで息絶えていたのが改善されるといいなあ…) <a href="https://t.co/UH73Q4pUmo">https://t.co/UH73Q4pUmo</a> <a href="https://t.co/KBnRAVGu3y">pic.twitter.com/KBnRAVGu3y</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1508029860714729472?ref_src=twsrc%5Etfw">2022年3月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>技術的な方法で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>の閲覧時間を削減する試みを開始(まあまあ役に立っており、今もつかっている)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">またいらぬ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%C8%C4%A5%B5%A1%C7%BD">拡張機能</a>を書いてしまったので今日は眠れそうです(このツイートをした後<a class="keyword" href="http://d.hatena.ne.jp/keyword/twitter">twitter</a> .com もリストに追加するのでアクセスできなくなる) <a href="https://t.co/WzQ6K91uKf">pic.twitter.com/WzQ6K91uKf</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1508829079503777794?ref_src=twsrc%5Etfw">2022年3月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="4月">4月</h2> <p>社の公式ブログでお仕事に関する記事を書いた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome%20OS">Chrome OS</a> が M100 に到達したのを記念して公式ブログに記事がたくさん上がっているのですが、そのうち一つを書いたので、興味があれば読んでみてください!<br><br>Making <a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a> Runtime on <a class="keyword" href="http://d.hatena.ne.jp/keyword/Chrome%20OS">Chrome OS</a> more secure and easier to upgrade with ARCVM<a href="https://t.co/kShpKe3C26">https://t.co/kShpKe3C26</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1509849791152672778?ref_src=twsrc%5Etfw">2022年4月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>Redox を読む会を始めた(次回をスケジュールするのを忘れていました…来年やります!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Rustで書かれたOS Redoxを読む会 #0 を公開しました! <a href="https://t.co/yoODIFKvhB">https://t.co/yoODIFKvhB</a> <a href="https://twitter.com/hashtag/reading_redox?src=hash&amp;ref_src=twsrc%5Etfw">#reading_redox</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1513083298146226176?ref_src=twsrc%5Etfw">2022年4月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>セキュキャンのC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミが、元受講生の講師を迎えて再始動することが決定(本当にめでたかった!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というわけでC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミ、新たな講師を迎えて復活です!!!<br>C<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミ卒業生である <a href="https://twitter.com/hsjoihs?ref_src=twsrc%5Etfw">@hsjoihs</a> さんと、Rustでブラウザを作れる <a href="https://twitter.com/uint256_t?ref_src=twsrc%5Etfw">@uint256_t</a> さんの最強タッグでお送りしますので、皆様ぜひぜひご応募ください!<br>(私が担当するOS自作ゼミも、よろしくお願いします!)<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/6jAFMkd1Lt">https://t.co/6jAFMkd1Lt</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1513437578326081537?ref_src=twsrc%5Etfw">2022年4月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ZOZOMATを試すなど(足、印刷しなきゃ…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">おー、ZOZOMAT便利だな…(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>作成の参考データにできそう) <a href="https://t.co/9Is8qYEXom">pic.twitter.com/9Is8qYEXom</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1515237066489020417?ref_src=twsrc%5Etfw">2022年4月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ちなみにイエベ春らしいです(ZOZOGLASS曰く)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ついでにZOZOGLASSもやってみたところ、よく人々が言ってるイエベ/ブルベが何を指しているのかようやく理解した。「元気で可愛らしい印象がある」本当か?(まあたしかに私の本体であるロゴの色とは合ってそうだが…) <a href="https://t.co/3WVq15AH3J">pic.twitter.com/3WVq15AH3J</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1515241944703668227?ref_src=twsrc%5Etfw">2022年4月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>社のイベントで人々に自作OSはいいぞ!をするなどした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんとか起床成功した…よろしくお願いします!一番最初の枠で喋ります! <a href="https://t.co/6Q7Cg2NEdc">https://t.co/6Q7Cg2NEdc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1518025358096089088?ref_src=twsrc%5Etfw">2022年4月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>スライドはここ</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">無事発表終わって一息ついてます…楽しんでいただけたなら幸いです!(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%B8%BB%FA%A5%B3%A1%BC%A5%C9">文字コード</a>が大好きな方や、OS自作をはじめた方、研究分野を転向してOSの研究室に入った方と発表後にお話しできて楽しかったです!)<br><br>本日発表したスライドはこちらです!<a href="https://twitter.com/hashtag/wtm22?src=hash&amp;ref_src=twsrc%5Etfw">#wtm22</a> <a href="https://t.co/pJMBCnF9Fc">https://t.co/pJMBCnF9Fc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1518061295777378304?ref_src=twsrc%5Etfw">2022年4月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして Asahi Lina さんとコラボした!(Linaさん、つよつよなので尊敬している)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%D0%A1%BC%A5%B9%A5%A8%A5%F3%A5%B8%A5%CB%A5%A2%A5%EA%A5%F3%A5%B0">リバースエンジニアリング</a>の解説をしてもらっている(たのしい!)<br><br>【Asahi Lina】M1 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a> であそぶ <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/Iucyh1biFb">https://t.co/Iucyh1biFb</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より <a href="https://t.co/wO6RPlNk7B">pic.twitter.com/wO6RPlNk7B</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1518887218940571648?ref_src=twsrc%5Etfw">2022年4月26日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>Linaさんのチャンネルにお邪魔して、私が自作OS語りをしてくる回もありました!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">🌟 Collab stream 🌟<br>Tomorrow (04/29) at 16:00 <a class="keyword" href="http://d.hatena.ne.jp/keyword/JST">JST</a> <a href="https://twitter.com/hikalium?ref_src=twsrc%5Etfw">@hikalium</a> and <a href="https://twitter.com/d0iasm?ref_src=twsrc%5Etfw">@d0iasm</a> from <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> will join me to <a class="keyword" href="http://d.hatena.ne.jp/keyword/talk">talk</a> about their <a class="keyword" href="http://d.hatena.ne.jp/keyword/DIY">DIY</a> OS and web browser! 🌎<br><br>If you enjoyed our M1 chat you definitely need to check this out! This time in English~!!<br><br>▶️ <a href="https://t.co/eWrTsRCvdH">https://t.co/eWrTsRCvdH</a> <a href="https://t.co/RbIEgfvPgj">pic.twitter.com/RbIEgfvPgj</a></p>&mdash; Asahi Lina / 朝日リナ // @lina@vt.social (@LinaAsahi) <a href="https://twitter.com/LinaAsahi/status/1519648586782613504?ref_src=twsrc%5Etfw">2022年4月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="5月">5月</h2> <p>kurenaif魔女のチャンネルにKOBA789氏と一緒にお邪魔して、<a href="https://dirtypipe.cm4all.com/">DirtyPipe</a> ( CVE-2022-0847 )を完全理解した</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">DirtyPipe完全理解した!<a href="https://twitter.com/fwarashi?ref_src=twsrc%5Etfw">@fwarashi</a> 氏の忍耐力と、 <a href="https://twitter.com/KOBA789?ref_src=twsrc%5Etfw">@KOBA789</a> 氏の聡明さにより、6時間の死闘の末 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a> Kernelのpipeとspliceまわりを行ごとに追いかけました!ぜひ!!<br><br>Dirty Pipeを解析する ~初めての<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>~【koba789, hikalium, kurenaif】 <a href="https://t.co/RqEYnTYQfP">https://t.co/RqEYnTYQfP</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より <a href="https://t.co/falii0DusD">pic.twitter.com/falii0DusD</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1521899110697107456?ref_src=twsrc%5Etfw">2022年5月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして弊チャンネル初のSuperThanks受領(ありがとうございます!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">初 Super Thanks いただいてました!ありがとうございます!<a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/hTv67MyN3S">pic.twitter.com/hTv67MyN3S</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1522178702272249856?ref_src=twsrc%5Etfw">2022年5月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>思い立ったのでosdev-jpのcode of conductを制定するなどした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">個人的には冒頭部分の文章がマジでosdev-jpって感じに仕上がったのでぜひ読んでほしい(多種多様なOSが栄える世界をつくっていきましょう〜) <a href="https://t.co/T9LiBvmZgo">https://t.co/T9LiBvmZgo</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1522580128769150982?ref_src=twsrc%5Etfw">2022年5月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>2月に公開した歌の解説記事を書いた(解説の必要な歌って、なに?)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「すいみんpreparation」の解説、という名の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B2%F8%CA%B8%BD%F1">怪文書</a>を放流しました(書くって言ったので有言実行です)(みなさんも安全でスムーズなsuspend to diskをしましょう!)<br><br><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%CF%A4%C6%A4%CA%A5%D6%A5%ED%A5%B0">はてなブログ</a>に投稿しました <a href="https://twitter.com/hashtag/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0?src=hash&amp;ref_src=twsrc%5Etfw">#はてなブログ</a><br>「すいみんpreparation」解説 - /var/log/hikalium <a href="https://t.co/Pedc6ribIi">https://t.co/Pedc6ribIi</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1523298516134957064?ref_src=twsrc%5Etfw">2022年5月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>があるなら、ということで3Dスキャナに入門した(むずかしい)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">3Dスキャン、なかなか難しい…(キーボードとかみたいな単調な繰り返し図形が入ってるとスキャンがずれるっぽいということがわかった)(例の帽子をスキャンしたらつばの部分が飛んでいきました) <a href="https://t.co/JddWxctJoK">pic.twitter.com/JddWxctJoK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1525838335037820928?ref_src=twsrc%5Etfw">2022年5月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>USB Type-C の電気的な側面の理解を試みるなどした(少し理解した)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">USB Type-C 難しい〜〜って言ってる <a href="https://t.co/vYWqfZwt9p">pic.twitter.com/vYWqfZwt9p</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1528352064082178048?ref_src=twsrc%5Etfw">2022年5月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして!はじめての!オフィスでの!夕食!(入社2年半以来初の快挙)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">この時を、どれほど待ち望んだことか…(入社以来2年半ほどお預けを食らっていたオフィスでの夕食がついに…!!!!) <a href="https://t.co/ift43hLEee">pic.twitter.com/ift43hLEee</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1528672022385291264?ref_src=twsrc%5Etfw">2022年5月23日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>分解衝動の発散</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">まーた気分の赴くままに分解していた(これはシー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%F3%A5%B0%A5%E9%A5%A4%A5%C8">リングライト</a>) <a href="https://t.co/kWDHwE2HT0">pic.twitter.com/kWDHwE2HT0</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1530350528798277633?ref_src=twsrc%5Etfw">2022年5月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="6月">6月</h2> <p>計算資源が追加された</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">My new 計算資源… <a href="https://t.co/1SvJFWCICH">pic.twitter.com/1SvJFWCICH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1538381645279277056?ref_src=twsrc%5Etfw">2022年6月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%D5%A4%EB%A4%B5%A4%C8%C7%BC%C0%C7">ふるさと納税</a>メロンを摂取(ひとりで2個まるごと食べるのはなかなかの難易度だった…超美味しかったけど…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">はやねはやおきして偉かったので朝っぱらからメロンを半個食べるという贅沢ムーブをします…(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%D5%A4%EB%A4%B5%A4%C8%C7%BC%C0%C7">ふるさと納税</a>でもらった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D9%CE%C9%CC%EE">富良野</a>メロンです) <a href="https://t.co/GBZC6foCiw">pic.twitter.com/GBZC6foCiw</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1541544239150288896?ref_src=twsrc%5Etfw">2022年6月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ついにToDoリストアプリをつくるというToDoに着手(現在メンテ中で落ちてる)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Doneを押せるようになったのでそろそろ出社するかあ <a href="https://t.co/4PwtWaWgyj">pic.twitter.com/4PwtWaWgyj</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1541577020806938629?ref_src=twsrc%5Etfw">2022年6月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="7月">7月</h2> <p>Rust for <a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>でお遊びする配信をするなどした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">前半は毎度おなじみ環境構築に手間取りましたが、後半は実際にRustで書かれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>モジュールを改造したり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>ランドだからできるpanic呼び出しもできたので大満足でした。ぜひ見てみてください!<a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/0jx2dl1nzl">https://t.co/0jx2dl1nzl</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1544303231656148994?ref_src=twsrc%5Etfw">2022年7月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>[大人の]科学を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BF%CD%C7%E3%A4%A4">大人買い</a>するなど</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BF%CD%A4%CE%B2%CA%B3%D8">大人の科学</a>と科学を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C2%E7%BF%CD%C7%E3%A4%A4">大人買い</a>した!(心は子供、財力は大人、なのでね!) <a href="https://t.co/LtjTykbHgV">pic.twitter.com/LtjTykbHgV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1546025949116104705?ref_src=twsrc%5Etfw">2022年7月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてRP2040を飛ばす</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">RP2040, ふつうに3Vの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%BF%A5%F3%C5%C5%C3%D3">ボタン電池</a>で稼働してえらい!(爆発音注意) <a href="https://t.co/l6eislECHV">pic.twitter.com/l6eislECHV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1546060485069774848?ref_src=twsrc%5Etfw">2022年7月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして破壊衝動の発散(ではなく異音の原因を除去した)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">もう少しでドラムの外側が見えるかな…? <a href="https://t.co/MVTmMpn01N">pic.twitter.com/MVTmMpn01N</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1547217746060275715?ref_src=twsrc%5Etfw">2022年7月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ちゃんと原因特定している図</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">おーけー、原因特定した(ドラムの裏を排水パイプ側から調べたら、どうも部品の一部が劣化したか破損したかして一部ちぎれて飛び出ていて、これを動かしたら音がしなくなったので除去しようと思う) <a href="https://t.co/6v2mVFuag1">pic.twitter.com/6v2mVFuag1</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1547227051283087360?ref_src=twsrc%5Etfw">2022年7月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>他の物体も分解(分解ばっかりしてるな)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日の分解はこちら!!!!!!!!!!<br>(水がたれてきたので仕方なく、ね…) <a href="https://t.co/ZQeWNiEssH">pic.twitter.com/ZQeWNiEssH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1551391900988747777?ref_src=twsrc%5Etfw">2022年7月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>Optaneはもうおしまいです、わたしは悲しいよ…(終わらせないぞ!!!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ところで悲しい話があってな…Optaneはもうおしまいらしい…<a class="keyword" href="http://d.hatena.ne.jp/keyword/Intel">Intel</a>さん信じてたのに…(在庫全部欲しい…可愛がってあげるから…)<br><br><a class="keyword" href="http://d.hatena.ne.jp/keyword/Intel">Intel</a> Kills Optane Memory Business Entirely, Pays $559 Million to Exit <a href="https://t.co/ATnMoxvN0Z">https://t.co/ATnMoxvN0Z</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1553098462753075203?ref_src=twsrc%5Etfw">2022年7月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%E8%C8%C7%B0%F5%BA%FE">活版印刷</a>入門</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%E8%C8%C7%B0%F5%BA%FE">活版印刷</a>入門した(?) <a href="https://t.co/2URvGGkp2R">pic.twitter.com/2URvGGkp2R</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1553740875943280646?ref_src=twsrc%5Etfw">2022年7月31日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="8月">8月</h2> <p>夏はやっぱりセキュキャン!自作OS!だよね!!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今年のOS開発ゼミの様子です!<br>(みんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>やメモリ管理やUSBデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の制御をバリバリやっていて楽しそう!)<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/DsY502TUTK">https://t.co/DsY502TUTK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1557221479062073344?ref_src=twsrc%5Etfw">2022年8月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと電源は大事です。電源は大事なので。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">My new power supply.... <a href="https://t.co/tTXpyYBR7w">pic.twitter.com/tTXpyYBR7w</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1557334799714754561?ref_src=twsrc%5Etfw">2022年8月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>の人々の優しい言葉に救われました。本当にありがとうございます!!!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日のよかったこと:社に行ったら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>の人々に「hikaliumさんのことをみんなが覚えてるのは、ちゃんと色々情報を発信したり言葉にできていてすごいなあって思ってるからですよ!」みたいなことを言ってもらえたこと(これからも頑張ります…ありがとう!)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1559212332601208832?ref_src=twsrc%5Etfw">2022年8月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして深淵を覗く</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">hikaliumを見つめるとき、hikaliumもまた見つめ返している… <a href="https://t.co/STSegqzH0Q">pic.twitter.com/STSegqzH0Q</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1561697521034231810?ref_src=twsrc%5Etfw">2022年8月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="9月">9月</h2> <p>はじめての入院入門!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">はじめての入院入門です!<br>(物理<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>の調整のため) <a href="https://t.co/ea1dBrojmD">pic.twitter.com/ea1dBrojmD</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1567023934725574659?ref_src=twsrc%5Etfw">2022年9月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ハードウェアアップデートのためしばらくオフラインに</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">hikaliumに重要な更新を適用しています。デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の電源を切らないでください…<br>(Close the world, open the next...) <a href="https://t.co/lKC3JpLugM">https://t.co/lKC3JpLugM</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1567345818528808960?ref_src=twsrc%5Etfw">2022年9月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>生還したので辞世の句にはならなかった歌ってみた動画</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">そういえば生還してました。ついでに歌ってみた動画も手術中に公開予約してたのでどうぞ…<a href="https://t.co/cIYAOAhXYK">https://t.co/cIYAOAhXYK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1567835319126622208?ref_src=twsrc%5Etfw">2022年9月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>2週間の入院後なんとか帰宅したら家は無事ではなかった話(またエアコンから水かよ(自力でなんとかしました))</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「いいニュースと悪いニュースがある」<br>「またか」<br>「いいニュースは、台風にそこまで影響を受けずに帰宅成功したことだ」<br>「ほう、めでたい。で、悪い方は?」<br>「…床が水浸しになっていた」<br>「君の神様はなかなか厳しいことをするね…」 <a href="https://t.co/fFL5Eedxks">pic.twitter.com/fFL5Eedxks</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1571705524399513603?ref_src=twsrc%5Etfw">2022年9月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>リコリコに影響されて「力」を手に入れるなど(もちろん合法な力です)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">リコリコ観てたら「力」が欲しくなったので調達した(すでに所有していたシビュラシステムの「力」を添えて) <a href="https://t.co/jhkGpDqiXu">pic.twitter.com/jhkGpDqiXu</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1571781300138409988?ref_src=twsrc%5Etfw">2022年9月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ikaliumです(入院中に発売されていたスプラ3に入門)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">久々のソイチューバ―系hikalium(本日の様子) <a href="https://t.co/s9FnAgQaL4">pic.twitter.com/s9FnAgQaL4</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1573711738213900293?ref_src=twsrc%5Etfw">2022年9月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="10月">10月</h2> <p>低レイヤーガール、チャンネル登録者数4000人突破!!(ありがとうございます!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というかチャンネル登録者数が4000人を超えていてびびっている。みんな低レイヤ大好きなんだなあ…(ありがとうございます!)<a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/Q7T5sibJMv">pic.twitter.com/Q7T5sibJMv</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1579436726832885760?ref_src=twsrc%5Etfw">2022年10月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>二次元セル<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%C8%A5%DE%A5%C8%A5%F3">オートマトン</a>を一発実装する THE FIRST CODE をやってみたら、しょうもない<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>エラーで終了した件(ちゃんと後で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>しました!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">main.c:40:2: error: expected &#39;;&#39; after struct<br><br>…ということで REVIEW TIME です!!(すぐはじめます!)<br><br>hikalium - 2D Cellular Automaton / THE FIRST CODE <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://twitter.com/hashtag/thefirstcode?src=hash&amp;ref_src=twsrc%5Etfw">#thefirstcode</a> <a href="https://t.co/nXShTPNXP9">https://t.co/nXShTPNXP9</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1579450412801093632?ref_src=twsrc%5Etfw">2022年10月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして新しい物理<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>のmetrics exporter(丸くてかわいいのでお気に入りです)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">My new <a class="keyword" href="http://d.hatena.ne.jp/keyword/watch">watch</a>...<a href="https://twitter.com/hashtag/PixelWatch?src=hash&amp;ref_src=twsrc%5Etfw">#PixelWatch</a> <a href="https://t.co/8Hkmh2xvQQ">pic.twitter.com/8Hkmh2xvQQ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1580861546112364544?ref_src=twsrc%5Etfw">2022年10月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>久々に物理世界のイベントに参加して自己肯定感が向上した図(hikaliumは優しい皆様に救われています)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">久々に物理世界のイベントに参加した結果、いつもの「まさか現実で会えるなんて嬉しい」に加えて「話がとても聞き取りやすい」「hikaliumさんの影響でセキュキャンそしてCODEBLUEに参加しました!」×2,「低レイヤーガールを観てみかん本を始めました!」等々の喜びの声が多数寄せられており…(要出典)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1586057725108027392?ref_src=twsrc%5Etfw">2022年10月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="11月">11月</h2> <p>情報公開(伏線回収)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">バグっていた物理<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>の機体登録情報の修正がついに許可された…(とはいえ私の本体は概念なのでそれ以外は何も変わりません。引き続きよろしくお願いします!) <a href="https://t.co/vY8mKBoEXV">pic.twitter.com/vY8mKBoEXV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1588905666772488193?ref_src=twsrc%5Etfw">2022年11月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>やさしい世界</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">諸々のお祝いを、数少ない中高時代からの親友たちに実施してもらいました。ほんと、よく生存したよ…ありがとうございました!(これからもがんばります!) <a href="https://t.co/fUA07d5A5l">pic.twitter.com/fUA07d5A5l</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1591735483121676290?ref_src=twsrc%5Etfw">2022年11月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そして<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>の浸透</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>、浸透したっぽい(浸透言うな)(というか84円使って55円を返還するの、ロックだなあ…(電子化してくれ)) <a href="https://t.co/7CJ5AHvFOh">pic.twitter.com/7CJ5AHvFOh</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1595747170011217921?ref_src=twsrc%5Etfw">2022年11月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>3年間お預けだった、リアルワールド開催のSTEP Class 8に参加してきた!(<a class="keyword" href="http://d.hatena.ne.jp/keyword/malloc">malloc</a>チャレンジの参加者の何名かに賞を差し上げました!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Worst-fit <a class="keyword" href="http://d.hatena.ne.jp/keyword/malloc">malloc</a>を体験したで賞、です!!!(パフォーマンスがめっちゃ下がったことに面白さを見出して、みんなに共有してくれたことに敬意を表しての賞でした!) <a href="https://t.co/NQCvyHiY9w">https://t.co/NQCvyHiY9w</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1596130748834385922?ref_src=twsrc%5Etfw">2022年11月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>テプラSR5900Pの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>を解析して、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>から印刷できるツールを実装した</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">TEPRA SR5900P、完全理解した(とりあえず embedded_graphics クレートで描けるものはなんでも書けるようになったので、あとは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>周りをもう少しきれいに整備したら幸せになれそう(あとでやる))<a href="https://t.co/EcrPEmBxfo">https://t.co/EcrPEmBxfo</a><a href="https://twitter.com/rustembedded?ref_src=twsrc%5Etfw">@rustembedded</a> <a href="https://t.co/z023lNHl7D">pic.twitter.com/z023lNHl7D</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1597019400514981888?ref_src=twsrc%5Etfw">2022年11月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>物質、いいよね(用法用量を守って正しく使いましょう)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">目が覚めそうな液体と、幸せな気分になれそうな液体を注ぐのに適したマグ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A5%C3%A5%D7">カップ</a>を入手した…(かわいいね) <a href="https://t.co/K9MnOMfWqU">pic.twitter.com/K9MnOMfWqU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1597908088904110080?ref_src=twsrc%5Etfw">2022年11月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="12月">12月</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DD%A5%B1%A5%E2%A5%F3">ポケモン</a>SV、はじめました!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">クレープを食べてご満悦なhikaliumさんと、新しいお友達を得たhikaliumさんの写真です… <a href="https://t.co/dFkDn36EzF">pic.twitter.com/dFkDn36EzF</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1598686279331614721?ref_src=twsrc%5Etfw">2022年12月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>Open Source Summit 聴講(社の人間としては初の物理カンファレンス参加)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">私のロゴのステッカーを貼っている人がいたらそいつがhikaliumの物理<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>です!(気軽に話しかけてくださいまし…) <a href="https://t.co/C5RyXNJ8lh">pic.twitter.com/C5RyXNJ8lh</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1599586498000883713?ref_src=twsrc%5Etfw">2022年12月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/WebUSB">WebUSB</a>に入門した(自作OSでドライバ実装したときの大変さに比べたらマジで拍子抜けするほど簡単でびっくりした、みんなもっとこれで遊ぼう!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">対話操作もできるようになった(雑実装だが動くのでOK)(Note: つないでいる対象は私物の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Chromebook">Chromebook</a>) <a href="https://t.co/P0c9ijocKL">pic.twitter.com/P0c9ijocKL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1601546890130034688?ref_src=twsrc%5Etfw">2022年12月10日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>/sys/hikalium/tracing を生やした(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>用なのでノイズが多いですが興味あればどうぞ)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenadiary.jp%2Fentry%2F2022%2F12%2F17%2F235833" title="echo 1 &gt; /sys/hikalium/tracing/events/enable - /sys/hikalium/tracing" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenadiary.jp/entry/2022/12/17/235833">hikalium.hatenadiary.jp</a></cite></p> <p>胸に刻んでおきたい言葉(手前味噌ですが)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ある分野が「やればできる」ようになっているのは文明の勝利であって、その事実がその分野や、それを習得した人の価値を下げることはない。どんな本も、開くことは誰にでもできるが、すべての本を読むことはできない。できることのうち何をしたか、その組み合わせにこそ唯一無二の価値があると思う。 <a href="https://t.co/7VCbJxrNno">https://t.co/7VCbJxrNno</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1604385328869289984?ref_src=twsrc%5Etfw">2022年12月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>hikaliumのロゴの背後の深層心理はこれでは?という発見</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">私の深層心理、これ疑惑あるな…(親の顔より見たカラーパターン) <a href="https://t.co/0azbMvNSsY">https://t.co/0azbMvNSsY</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1604412923731800065?ref_src=twsrc%5Etfw">2022年12月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>no (クリスマス) spanning-tree</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">メリークリスマス! <a href="https://t.co/iyOnaMiPKU">pic.twitter.com/iyOnaMiPKU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1606907890274795520?ref_src=twsrc%5Etfw">2022年12月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>大掃除</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日の破壊 <a href="https://t.co/dxKoiQg9i1">pic.twitter.com/dxKoiQg9i1</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1608420369123409925?ref_src=twsrc%5Etfw">2022年12月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>著者近影</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">だいぶそれっぽく仕上がってきたのだが、なぜもうこんな時刻なのですか?(急いで眠ります) <a href="https://t.co/f6gEaPwr9N">pic.twitter.com/f6gEaPwr9N</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1608546813002518529?ref_src=twsrc%5Etfw">2022年12月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h2 id="総括">総括</h2> <p>振り返ってみれば、想像以上にたくさんのことをやっていたことに気づいた。もっと自信を持って欲しい > 自分</p> <p>ついに情報公開も果たしたが、誰もが何事もなく受け止めてくれて、人々の優しさを再確認した。これからは、以前にも増して、自分の「好き」をもっと大切にしてゆきたいと思う。(みなさんもぜひ、そうしてくださいね!)</p> <p>おしごとに関しては、外から見える範囲のCommunity contributionをたくさんできたのは素晴らしかったし、これからも続けてゆきたいが、もっと強くなって技術的な成果のほうもさらに挙げてゆきたい。問題は、時間が足りないというところだが…(生き残りたい!!!)</p> <p>あと、もう少し精神を安定させてゆきたいですね。もっと、ゆっくり、やっていこう。活動を抑え気味にしているつもりでも、これだけのことをできているのだから。</p> <p>今年お世話になった皆様におかれましては、本当にありがとうございました。</p> <p>来年以降も引き続き精進してまいりますので、hikaliumをどうかよろしくお願いいたします!!!</p> hikalium Rustで自作OSをしているときのデバッグ例 - syscall 命令と仲良くなりたい!後編 hatenablog://entry/4207112889945996769 2022-12-19T01:17:22+09:00 2022-12-19T01:17:22+09:00 この記事は自作OS Advent Calendar 2022の18日目の記事です。前回のあらすじはこちら: hikalium.hatenablog.jp 例外を吐いてるのはどこのどいつだぁ? さて、前回の状況をおさらいすると、 0x200fd0の命令がアドレス0x2000000000にアクセスしようとしてページフォルト(0xe)を発生させた。 ページフォルトを処理している最中に一般保護例外(0xd)が発生し、一般保護例外を処理中にもさらに一般保護例外が発生することで、順次スタックが食い潰されていった。 例外ハンドラのスタックが枯渇し、0x3de4bed8にアクセスしようとした段階でページフォル… <p>この記事は<a href="https://adventar.org/calendars/8392">自作OS Advent Calendar 2022</a>の18日目の記事です。前回のあらすじはこちら:</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2022%2F12%2F17%2F234450" title="Rustで自作OSをしているときのデバッグ例 - syscall 命令と仲良くなりたい!前編 - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2022/12/17/234450">hikalium.hatenablog.jp</a></cite></p> <h1 id="例外を吐いてるのはどこのどいつだぁ">例外を吐いてるのはどこのどいつだぁ?</h1> <p>さて、前回の状況をおさらいすると、</p> <ul> <li>0x200fd0の命令がアドレス0x2000000000にアクセスしようとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)を発生させた。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>を処理している最中に一般保護例外(0xd)が発生し、一般保護例外を処理中にもさらに一般保護例外が発生することで、順次スタックが食い潰されていった。</li> <li>例外ハンドラのスタックが枯渇し、0x3de4bed8にアクセスしようとした段階で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>が発生した。これにより、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>が発生した。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>ハンドラ内で再度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>が発生した結果、トリプルフォルトとなってリセットがかかった。</li> </ul> <p>というわけで、まずは最初のきっかけである 0x200fd0とかにある命令がどこのどいつかを特定することにしましょう。</p> <p>まず、アプリのロード状況を確認します。OSのログを見ると、</p> <pre class="code" data-lang="" data-unlink>Executable found: Elf { name: hello, data: @0x000000003e2d9000 } This ELF seems to be executable! phdr_start: 64, phdr_entry_size: 56, num_of_phdr_entry: 5 type : (rwx) = (101) offset: 0x0000000000000000 vaddr : 0x0000000000200000 fsize : 0x0000000000001B64 vsize : 0x0000000000001B64 align : 0x0000000000001000 type : (rwx) = (110) offset: 0x0000000000001B68 vaddr : 0x0000000000202B68 fsize : 0x00000000000001C8 vsize : 0x00000000000001C8 align : 0x0000000000001000 load_region_start = 0x0000000000200000 load_region_end = 0x0000000000203000 load_region @ 0x000000003d233000 dst_range: 0x0000000000000000 - 0x0000000000001B64 dst_range: 0x0000000000002B68 - 0x0000000000002D30 run the code! entry_point = 0x000000003d2332f0</pre> <p>というふうになっています。これはどういうことかというと…図示したほうがはやそうなので、お絵描きしました。</p> <p><figure class="figure-image figure-image-fotolife" title="現在のアプリケーションのロードの様子"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20221218/20221218014309.png" width="1200" height="725" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>現在のアプリケーションのロードの様子</figcaption></figure></p> <p>現在は手抜きをするために、アプリケーションとOSのメモリ空間を分けていないので、アプリの希望通りのメモリレイアウトではなく、相対位置を維持したまま、異なるアドレスにCodeとDataの両方をロードしているのでした。</p> <p>さて、例外を発生させたメモリアドレス(0x200fd0)は、このロードされたコード(0x3d233000-0x3d234b64)の中…にありませんね…あれ?</p> <p>…と思って状況をよくよく確認すると、どうもこのアドレスは、アプリがもともと予期していた、コード領域がロードされるべきアドレス範囲(0x200000-0x201b64)の中にあるようです…つまり、アプリケーションが正しく再配置可能ではなかった、もしくはローダーが仕事をサボっているせいで、正しく再配置できなかった、のいずれかの可能性であると考えられます。ちょっとアプリのバイナリのほうを確認してみましょう。</p> <pre class="code" data-lang="" data-unlink>$ `brew --prefix binutils`/bin/objdump -d -C target/x86_64-unknown-elf/release/hello | grep -A 3 200fd0 0000000000200fd0 &lt;&lt;core::fmt::Arguments as core::fmt::Display&gt;::fmt&gt;: 200fd0: 48 83 ec 38 sub $0x38,%rsp 200fd4: 48 8b 06 mov (%rsi),%rax 200fd7: 48 8b 76 08 mov 0x8(%rsi),%rsi 200fdb: 48 8b 4f 28 mov 0x28(%rdi),%rcx</pre> <p>objdumpに-Cオプションをつけると、シンボルをデマングル(人間が読みやすい形式に変換)してくれるみたいで、Rustのシンボル名にも対応してるみたいです。ありがとう<a class="keyword" href="http://d.hatena.ne.jp/keyword/binutils">binutils</a>!</p> <p>というわけでですね、この200fd0は、明らかにDisplay::fmtを呼び出しているコードで利用されていて、我々のprintln!のコードパスで通っていそうな雰囲気がひしひしと伝わってきます。</p> <p>さて、これを呼び出している側のコードはどうなっているのでしょうか?rip相対のcallではこのようなことは起こり得ないので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>間接でのcallがDisplay::fmtへ制御を移そうとしているはずです。なので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>間接callを使っている人々をリストアップしましょう。</p> <pre class="code" data-lang="" data-unlink>$ `brew --prefix binutils`/bin/objdump -d -C target/x86_64-unknown-elf/release/hello | grep -E -e &#39;call.*\*&#39; -e &#39; &lt;.*&gt;:$&#39; | grep &#39;call.*\*&#39; -B 1 0000000000200860 &lt;&lt;core::panic::panic_info::PanicInfo as core::fmt::Display&gt;::fmt&gt;: 200886: 41 ff 56 18 call *0x18(%r14) 2008bf: ff 50 18 call *0x18(%rax) -- 0000000000201030 &lt;core::fmt::write&gt;: 2010b7: ff 50 18 call *0x18(%rax) 201177: ff 54 08 08 call *0x8(%rax,%rcx,1) 2011d8: ff 50 18 call *0x18(%rax) 2011e9: 42 ff 54 35 08 call *0x8(%rbp,%r14,1) 20122f: ff 51 18 call *0x18(%rcx) 0000000000201250 &lt;core::fmt::Formatter::pad_integral&gt;: 2013f1: ff 55 20 call *0x20(%rbp) 20150a: 41 ff 55 20 call *0x20(%r13) 201557: ff 55 18 call *0x18(%rbp) 201582: 41 ff 55 18 call *0x18(%r13) 2015aa: 41 ff 55 20 call *0x20(%r13) 00000000002015d0 &lt;core::fmt::Formatter::pad_integral::write_prefix&gt;: 2015f1: 41 ff 54 24 20 call *0x20(%r12) 0000000000201630 &lt;core::fmt::Formatter::pad&gt;: 2018ea: 41 ff 56 20 call *0x20(%r14) 20190d: 41 ff 56 18 call *0x18(%r14) 20193f: 41 ff 56 20 call *0x20(%r14)</pre> <p>まあ…たぶんcore::fmt::writeですよね…きっとそうだ…</p> <pre class="code" data-lang="" data-unlink>`brew --prefix binutils`/bin/objdump -d -C target/x86_64-unknown-elf/release/hello | grep &#39;&lt;core::fmt::write&gt;:&#39; -A 155 | grep -z -E -e &#39;call&#39; --color=&#39;always&#39;</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/qemu">qemu</a>/target/<a class="keyword" href="http://d.hatena.ne.jp/keyword/i386">i386</a>/cpu.h</p> <pre class="code" data-lang="" data-unlink>$ cat qemu_debug.log | grep hikalium | head -n 3 hikalium: raise_interrupt2: is_int == 0 intno = 14 eip=0x000000000000200FD0 error_code = 0x000000000000000000 hikalium: rsp: 00000000003E286BE0 hikalium: ret_to: 00000000003D2341EE</pre> <pre class="code" data-lang="" data-unlink>$ cat com2.log | grep -a -e entry_point entry_point = 0x000000003d2332f0</pre> <pre class="code" data-lang="" data-unlink>$ make objdump_hello | grep &#39;&lt;entry&gt;:&#39; 00000000002002f0 &lt;entry&gt;:</pre> <pre class="code" data-lang="" data-unlink>$ ./scripts/debug/inspect_app_crash.sh 0000000000201030 &lt;core::fmt::write&gt;: 2011e9: 42 ff 54 35 08 call *0x8(%rbp,%r14,1) 2011ee: 84 c0 test %al,%al</pre> <p><code>.data.rel.ro</code>があやしい!</p> <p><a href="https://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/specialsections.html">https://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/specialsections.html</a></p> <p><a href="https://chromium.googlesource.com/chromium/src/+/HEAD/docs/native_relocations.md">Chromium Docs - Native Relocations</a></p> <p><a href="https://maskray.me/blog/2021-10-30-relative-relocations-and-relr">Relative relocations and RELR | MaskRay</a></p> <pre class="code" data-lang="" data-unlink>$ `brew --prefix binutils`/bin/objcopy -O binary --only-section=.data.rel.ro generated/bin/hello data.bin [00:34:16] [local] hikalium@t05.z01.hikalium.com: ~/repo/wasabi $ hexdump -C data.bin 00000000 58 01 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |X. .............| 00000010 58 01 20 00 00 00 00 00 01 00 00 00 00 00 00 00 |X. .............| 00000020 58 01 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |X. .............| 00000030 e0 04 20 00 00 00 00 00 08 00 00 00 00 00 00 00 |. .............| 00000040 08 00 00 00 00 00 00 00 20 06 20 00 00 00 00 00 |........ . .....| 00000050 f0 04 20 00 00 00 00 00 c0 05 20 00 00 00 00 00 |. ...... .....| 00000060 60 01 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |`. .............| 00000070 60 01 20 00 00 00 00 00 01 00 00 00 00 00 00 00 |`. .............| 00000080 61 01 20 00 00 00 00 00 08 00 00 00 00 00 00 00 |a. .............| 00000090 60 01 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |`. .............| 000000a0 e0 04 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |. .............| 000000b0 01 00 00 00 00 00 00 00 70 07 20 00 00 00 00 00 |........p. .....| 000000c0 b0 03 20 00 00 00 00 00 80 04 20 00 00 00 00 00 |. ....... .....| 000000d0 e0 04 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |. .............| 000000e0 01 00 00 00 00 00 00 00 70 19 20 00 00 00 00 00 |........p. .....| 000000f0 94 01 20 00 00 00 00 00 13 00 00 00 00 00 00 00 |.. .............| 00000100 37 00 00 00 05 00 00 00 94 01 20 00 00 00 00 00 |7......... .....| 00000110 13 00 00 00 00 00 00 00 53 00 00 00 05 00 00 00 |........S.......| 00000120 db 01 20 00 00 00 00 00 01 00 00 00 00 00 00 00 |. .............| 00000130 dc 01 20 00 00 00 00 00 03 00 00 00 00 00 00 00 |. .............| 00000140 a8 02 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |. .............| 00000150 a8 02 20 00 00 00 00 00 01 00 00 00 00 00 00 00 |. .............| * 00000170 40 1a 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |@. .............| 00000180 01 00 00 00 00 00 00 00 50 08 20 00 00 00 00 00 |........P. .....| 00000190 b8 02 20 00 00 00 00 00 00 00 00 00 00 00 00 00 |. .............| 000001a0 b8 02 20 00 00 00 00 00 02 00 00 00 00 00 00 00 |. .............| 000001b0 </pre> <p><a href="https://uclibc.org/docs/elf-64-gen.pdf">https://uclibc.org/docs/elf-64-gen.pdf</a></p> <p><a href="https://www.redhat.com/en/blog/hardening-elf-binaries-using-relocation-read-only-relro">Hardening ELF binaries using Relocation Read-Only (RELRO)</a></p> <p><a href="https://maskray.me/blog/2021-08-29-all-about-global-offset-table">https://maskray.me/blog/2021-08-29-all-about-global-offset-table</a></p> <p><a href="https://www.airs.com/blog/archives/189">Airs &ndash; Ian Lance Taylor &raquo; Linker relro</a></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcnlelema.github.io%2Fmemo%2Fen%2Fcodegen%2Fbasic-elf%2Frelocation%2F" title="Lele&#39;s Memo: Relocation Section" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cnlelema.github.io/memo/en/codegen/basic-elf/relocation/">cnlelema.github.io</a></cite></p> <h2 id="時間切れ">時間切れ</h2> <p>というわけで追いかけていたら.data.rel.roの沼にはまったので今日はここまで。明日もやるかも。おやすみなさい…。</p> hikalium Rustで自作OSをしているときのデバッグ例 - syscall 命令と仲良くなりたい!前編 hatenablog://entry/4207112889945908097 2022-12-17T23:44:50+09:00 2022-12-17T23:44:50+09:00 この記事は自作OS Advent Calendar 2022の17日目の記事です。他の記事も是非お楽しみください!(そして書ける方はぜひ参加してみてください!!) 前回(?)までのあらすじ hikaliumは自作OS上で動くアプリからsyscall命令を使ってシステムコールを呼べるようにしようと頑張っていたが、なぜか発生するトリプルフォルトによりQEMUが再起動してしまい、3時間のデバッグの末力尽きてしまった。一体なぜ例外が発生するのか、その謎を解くため、我々は数日の休息をとったのち、バイナリの森へと旅立った…。 前回(という名の配信アーカイブ): www.youtube.com 状況を整理し… <p>この記事は<a href="https://adventar.org/calendars/8392">自作OS Advent Calendar 2022</a>の17日目の記事です。他の記事も是非お楽しみください!(そして書ける方はぜひ参加してみてください!!)</p> <h1 id="前回までのあらすじ">前回(?)までのあらすじ</h1> <p>hikaliumは自作OS上で動くアプリからsyscall命令を使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>を呼べるようにしようと頑張っていたが、なぜか発生するトリプルフォルトにより<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>が再起動してしまい、3時間の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>の末力尽きてしまった。一体なぜ例外が発生するのか、その謎を解くため、我々は数日の休息をとったのち、バイナリの森へと旅立った…。</p> <p>前回(という名の配信<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>):</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/cDUX7-bzLC0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen title="自作OS作業配信 - 自作OSで println! をサポートする #low_layer_girls"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=cDUX7-bzLC0">www.youtube.com</a></cite></p> <h1 id="状況を整理しよう">状況を整理しよう</h1> <p>バイナリの森は危険だ。無闇に動きまわっては、<a class="keyword" href="http://d.hatena.ne.jp/keyword/x86">x86</a>の沼に足をとられて命を落としかねない。まずは我々の向かっていた先と、これまでに得た情報をまとめることにしよう。</p> <h2 id="どこへ向かっていたのか">どこへ向かっていたのか</h2> <p>我々のひとまずの目標は、自作OS上で実行されるアプリケーションから、Rustのprintln!()マクロを介して文字列を出力することであった。Rustはとてもよくできていて、coreクレートの中に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>でいうsprintfに相当する、fmtモジュールが存在しており、既存のOSの支援が期待できないno_std環境でも変数の中身などを容易にかつ美しく表示する関数およびマクロを容易に実装することができる。そう、我々はもう闇のようなlibc++やnewlibに頼らなくてもよくなったのだ。10年前のように、自前でsnprintfもどきを実装するまでもない。世界は日増しによくなりつつある。</p> <p>ではprintln!マクロを実装するにあたり、自作OSが提供しなければならない機能は一体何かというと、それは「文字列を表示する」という機能である。というのも、coreクレートにはOSに依存するような機能は含められないため、「文字を画面に出す」などといった、物理世界とのインタ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E9%A5%AF">ラク</a>ション、つまりはハードウエアの制御などのOSが支配している領域の操作はcoreクレートの外で自前で用意してやらなければならない。core::fmtは、フォーマット文字列と引数をもとに、メモリ上に「表示するべき文字列」を生成してはくれるが、それを表示するのは我々の責務なのだ。</p> <p>というわけで、我々はprint_stringという<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>を用意した。これは、メモリ上に存在する文字列へのポインタと、文字列の長さを指定すると、OSがそれを画面上に表示してくれる、というものである。実は、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>自体はどうも動作しているようで、実際にアプリケーションからprint_string<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>を介して固定の文字列を出力してみた場合は、想定通りに文字列が出力されていたことが確認できている。</p> <p>それならば、あとはprint_stringに対して、core::fmtによって生成された文字列を渡してあげればよいのではないか、我々はそう踏んでいたのだ。</p> <h2 id="なにがあったのか">なにがあったのか</h2> <p>…しかし、その考えはあまりにも浅はかだった。実際に、以下のようにprint_stringを置き換えてみたところ、なんとOSが再起動してしまったのだ。</p> <pre class="code Rust" data-lang="Rust" data-unlink>#![no_std] #![no_main] use noli::*; fn main() -&gt; i64 { //sys_print(&#34;hello!&#34;); println!(&#34;{}&#34;, 42); return -42; } entry_point!(main);</pre> <p>どうも、何らかの理由でCPUの例外が発生し、トリプルフォルトに至って再起動してしまう、というところまではわかったのだが、我々はそこで一旦力尽きてしまったのだった…。</p> <h1 id="まずは何が起きているのかを理解しよう">まずは何が起きているのかを理解しよう</h1> <p>現状は先ほど伝えた通りだ。次は、我々がどちらに向かえばよいのか、それを考えることにしよう。そのためには、我々がいま直面している現象を正しく理解することが必要不可欠だ。まずは、具体的にどのような例外でトリプルフォルトに至っているのか、それを確認することにしよう。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>には、例外が発生した際にログを出力する機能が存在している。これはデフォルトでオフになっているが、<code>-d</code> というフラグを介して制御することが可能だ。</p> <pre class="code" data-lang="" data-unlink>$ qemu-system-x86_64 -d ? Log items (comma separated): out_asm show generated host assembly code for each compiled TB in_asm show target assembly code for each compiled TB op show micro ops for each compiled TB op_opt show micro ops after optimization op_ind show micro ops before indirect lowering int show interrupts/exceptions in short format exec show trace before each executed TB (lots of logs) cpu show CPU registers before entering a TB (lots of logs) fpu include FPU registers in the &#39;cpu&#39; logging mmu log MMU-related activities pcall x86 only: show protected mode far calls/returns/exceptions cpu_reset show CPU state before CPU resets unimp log unimplemented functionality guest_errors log when the guest OS does something invalid (eg accessing a non-existent register) page dump pages at beginning of user mode emulation nochain do not chain compiled TBs so that &#34;exec&#34; and &#34;cpu&#34; show complete traces plugin output from TCG plugins strace log every user-mode syscall, its input, and its result tid open a separate log file per thread; filename must contain &#39;%d&#39; trace:PATTERN enable trace events Use &#34;-d trace:help&#34; to get a list of trace events.</pre> <p>おっと、言い忘れていたが、我々は以下のバージョンの<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>を自前ビルドして利用している。一応伝えておこう。</p> <pre class="code" data-lang="" data-unlink>$ qemu-system-x86_64 --version QEMU emulator version 7.2.0 (v7.2.0-dirty) Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers</pre> <p>さて、本筋に戻るとしようか。というわけで、以下のようなオプションを<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>に追加すれば、例外に関するログが、カレント<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リの <code>qemu_debug.log</code> というファイルに出力されるはずである。(出力先のファイルは<code>-D</code>オプションで指定している。) また、 <code>--no-reboot</code> をつけておくと、トリプルフォルトでCPUにリセットがかかった際に、再起動するのではなく<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>を終了することができるようになる。再起動のループを楽しみたい気分であるなら話は別だが、これも設定しておくと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>が楽になるだろう。</p> <pre class="code" data-lang="" data-unlink>-d int,cpu_reset -D qemu_debug.log --no-reboot</pre> <p>さて、これでもう一回自作OSを起動してみる。アプリは自動で起動するように設定してあるから、クラッシュしてすぐ<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>が落ちるはずだ。</p> <p>…予想通り落ちた。ログを確認しよう。</p> <pre class="code" data-lang="" data-unlink>$ cat qemu_debug.log | grep -A 1 -e check_exception -e Triple check_exception old: 0xffffffff new 0xe 159: v=0e e=0000 i=0 cpl=0 IP=0008:0000000000200fd0 pc=0000000000200fd0 SP=0010:000000003e286be0 CR2=0000002000000000 -- check_exception old: 0xffffffff new 0xd 160: v=0d e=0000 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003e286928 env-&gt;regs[R_EAX]=0000002000000000 -- check_exception old: 0xffffffff new 0xd 161: v=0d e=0000 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003e286668 env-&gt;regs[R_EAX]=0000002000000000 -- ... -- check_exception old: 0xffffffff new 0xd 6458: v=0d e=0000 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003de4c1a8 env-&gt;regs[R_EAX]=0000002000000000 -- check_exception old: 0xffffffff new 0xd 6459: v=0d e=0000 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003de4bee8 env-&gt;regs[R_EAX]=0000002000000000 -- check_exception old: 0xd new 0xe 6460: v=0e e=0002 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003de4bee8 CR2=000000003de4bed8 -- check_exception old: 0xe new 0xe 6461: v=08 e=0000 i=0 cpl=0 IP=0008:000000003e290f91 pc=000000003e290f91 SP=0010:000000003de4bee8 env-&gt;regs[R_EAX]=0000002000000000 -- check_exception old: 0x8 new 0xe Triple fault</pre> <p>おお、結構な量のログが出ている。はて、一体何が起きているのだろうか…。</p> <p>例外コードを順に追っていくと、以下のような流れで例外が起きていることがわかる。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)が0x200fd0の命令を実行中に発生した。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>の要因となったアドレスは CR2=0x2000000000 である。</li> <li>一般保護例外(0xd)が0x3e290f91の命令を実行中に発生した。</li> <li>同じ例外が次々と発生し、スタックポインタが0x3e286928から0x3de4bee8まで変化した。</li> <li>最終的に、スタックポインタと同じアドレスであるCR2=0x3de4bed8 にアクセスしようとして、再度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)が発生した。</li> <li>ここでさらに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)が発生し、これによって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>(0x8)が発生した。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>(0x8)の発生中にさらに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)が発生し、最終的にトリプルフォルトとなってリセットがかかった。</li> </ul> <p>つまるところ、</p> <ul> <li>最初のきっかけは、0x200fd0の命令がアドレス0x2000000000にアクセスしようとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>(0xe)を発生させたことにある。</li> <li>その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>を処理している最中に一般保護例外(0xd)が発生し、一般保護例外を処理中にもさらに一般保護例外が発生することで、順次スタックが食い潰されていった。</li> <li>例外ハンドラのスタックが枯渇し、0x3de4bed8にアクセスしようとした段階で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>が発生した。これにより、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>が発生した。</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%D6%A5%EB%A5%D5%A5%A9%A5%EB%A5%C8">ダブルフォルト</a>ハンドラも同一のスタックを使用していたため、再度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A1%BC%A5%B8%A5%D5%A5%A9%A5%EB%A5%C8">ページフォルト</a>が発生し、トリプルフォルトとなってリセットがかかった。</li> </ul> <p>ということのようだ。 …例外を正しく処理できないOSでごめんなさい…(仕方ないよ、完璧なOSなんて存在しないもの。直していきましょう!)</p> <p>さて、ここらへんで日付変更線が近づいてきたようだ。続きはまた明日…(睡眠は大事ですよ!おやすみなさい!)</p> hikalium 「すいみんpreparation」解説 hatenablog://entry/13574176438079899424 2022-05-08T22:45:54+09:00 2022-05-08T22:45:54+09:00 注意: この文章は教科書ではありませんし正確性も保証されていません。より詳細で正確な情報を知りたい場合には、ここで登場したキーワードをもとに自分で調べてみてください。 はじめに 眠れない夜にOSのことを考えていたら、ふとメロディを思いついてしまったのでそれを打ち込んだのが2/2のことでした。 中途覚醒からの創作意欲の高まりを脳の外にダンプする作業が完了したので再度サスペンドモードに移行します— hikalium (@hikalium) 2022年2月1日 そこから勢いで曲を打ち込んで歌詞をつくり(この段階で歌詞は出来上がっていたので伏線) 「やりたいことばかりで リソース不足まっしぐらなの」を… <p>注意: この文章は教科書ではありませんし正確性も保証されていません。より詳細で正確な情報を知りたい場合には、ここで登場したキーワードをもとに自分で調べてみてください。</p> <h1>はじめに</h1> <p>眠れない夜にOSのことを考えていたら、ふとメロディを思いついてしまったのでそれを打ち込んだのが2/2のことでした。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C3%E6%C5%D3%B3%D0%C0%C3">中途覚醒</a>からの創作意欲の高まりを脳の外にダンプする作業が完了したので再度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%B9%A5%DA%A5%F3%A5%C9">サスペンド</a>モードに移行します</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1488624678780358658?ref_src=twsrc%5Etfw">2022年2月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そこから勢いで曲を打ち込んで歌詞をつくり(この段階で歌詞は出来上がっていたので伏線)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「やりたいことばかりで リソース不足まっしぐらなの」を加速させてくるね…(なぜ人生はこんなにも短いのか)<a href="https://t.co/d5kgIV0VXd">https://t.co/d5kgIV0VXd</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1494317733881606149?ref_src=twsrc%5Etfw">2022年2月17日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>歌って動画を作った結果がこちらです。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">また謎のうたを作ってしまった…<br>睡眠とスケジューリングが苦手なOSのみなさんにおすすめです(?)<br><br>すいみんpreparation - hikalium <a href="https://t.co/SXSIy15DZd">https://t.co/SXSIy15DZd</a> <a href="https://t.co/uRz2IXrNfE">pic.twitter.com/uRz2IXrNfE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1497171371431923715?ref_src=twsrc%5Etfw">2022年2月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なお歌はあまり上手くないので、声なしのバージョンがいいよという方は<a class="keyword" href="http://d.hatena.ne.jp/keyword/SoundCloud">SoundCloud</a>にありますのでそちらもどうぞ!</p> <p><iframe width="100%" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F1231052494&show_artwork=true"></iframe><cite class="hatena-citation"><a href="https://soundcloud.com/hikalium/preparation-instruments">soundcloud.com</a></cite></p> <p>さて、この曲に対する人々の反応ですが、</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">hikalium何やってんの???</p>&mdash; κeen (@blackenedgold) <a href="https://twitter.com/blackenedgold/status/1499687049259290625?ref_src=twsrc%5Etfw">2022年3月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>はい、極めて正常な反応だと思います。</p> <p>実のところ、この歌詞にはOSネタを大量に盛り込んでいたので、おそらくそのあたりの知識がないと完全には面白さが伝わらなかった可能性があります。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「すいみんpreparation」には OSネタを割といっぱい詰め込んだのでそのうち解説記事書こう(解説記事の必要な歌とは?)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1499687002865750016?ref_src=twsrc%5Etfw">2022年3月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そこで本記事では、「すいみんpreparation」の歌詞を追いつつ、どのようにOSネタとの関連があるのか、どのような意図をこめた歌詞になっているのかについて解説したいと思います。</p> <h1>全体のテーマ</h1> <p>動画の概要欄に「やりたいことで手一杯なOSのみなさんのために」と書かれている通り、OSの果たす役割のうちの一つである「資源の管理」という側面について、その難しさを日常生活になぞらえて描写することが今回のテーマでした。</p> <p>特に、タスクのスケジューリング問題に関しては、かなり強い仮定をおいてもなお<a class="keyword" href="http://d.hatena.ne.jp/keyword/NP%B4%B0%C1%B4">NP完全</a>な問題であることが "NP-complete scheduling problems" (J.D. Ullman, 1975) で示されています。ちなみにUllman氏は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>を実装したことのある皆様にはおなじみ、通称<a href="https://www.amazon.co.jp/dp/0321486811/">ドラゴンブック</a>の作者の一人です。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sciencedirect.com%2Fscience%2Farticle%2Fpii%2FS0022000075800080" title="NP-complete scheduling problems" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.sciencedirect.com/science/article/pii/S0022000075800080">www.sciencedirect.com</a></cite></p> <p>OSのみなさんだけでなく、人間のみなさんにとっても、日々遂行しなければならないタスクが山積していて、その処理に追われているという状況はよくみられることでしょう。</p> <p>そのような困難な状況下にあっても、最優先で処理すべきタスクのひとつ、それが睡眠である、というのが本作品の主要な論点になります。</p> <h1>歌詞とその背景</h1> <p>では、最初から順番に歌詞を追ってゆきましょう。</p> <pre class="code" data-lang="" data-unlink>いつも気づいたら 時計の針はとびまわり  明日という日が 足音立てず向かってくるよ</pre> <p>作業に没頭していると、時間があっという間に過ぎてしまって、気づけば夜中になっていた!という経験はみなさんよくあるのではないでしょうか。</p> <p>OSにおいては、並行処理における競合状態を回避するために「割り込み」を禁止することがあります。(このような競合状態の発生する可能性のある処理の範囲のことを、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%EA%A5%C6%A5%A3%A5%AB%A5%EB%A5%BB%A5%AF%A5%B7%A5%E7%A5%F3">クリティカルセクション</a>」と呼びます。)</p> <p>「割り込み」は、外部デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>からの信号などを契機として、現在実行している処理に優先してなんらかの処理を行わせる仕組みのこと、またそれを引き起こす信号のことを指します。</p> <p>割り込みを発生させる外部デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の状態変化の例としては、キーボードのキーを押下した時や、ネットワークを介してパケットが到着した時、外部記憶装置に対する書き込み要求が完了した時などが挙げられます。</p> <p>他にも、重要かつ基本的な割り込みの一つとして、タイマー割り込みというものが存在します。これは、ある時間(たとえば10ms)が経過するごとに割り込みを発生させる、というものです。</p> <p>OSは、このタイマー割り込みを活用することにより、時分割<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%BF%A5%B9%A5%AF">マルチタスク</a>を実現しています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%BF%A5%B9%A5%AF">マルチタスク</a>は、CPUの処理能力という限られた資源を有効活用するというOSの大事な役割のひとつです。 したがって、それを支えるタイマーや時刻の管理も、実はOSの重要な仕事のひとつなのです。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>ではtimekeepingサブシステムがこれを担当しています。)</p> <p>さて、以上のことを念頭に一つ考えてみることにしましょう。もしも割り込みをずっと止めていたら、つまり割り込みを無視し続けたら、一体何が起こるでしょうか?</p> <p>……そうです、時分割<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%BF%A5%B9%A5%AF">マルチタスク</a>の仕組みが正しく動作せず、現在実行しているタスクが終わるまでずっとそのタスクを処理しつづけることになります。</p> <p>これは、何かに没頭して時間の経過を忘れてしまうことと対応します。(人間においてこのような状況は「過集中」と呼ばれることもあります。)</p> <p>その結果として、いつの間にか意図せず夜ふかしをしてしまうことを「明日という日が 足音立てず向かってくるよ」と表現しています。</p> <p>また、タイマー割り込みによって定期的に行われていた時刻の管理も正しく行われなくなるため、時計が狂ってしまうこともあります。</p> <p>それが「いつも気づいたら 時計の針はとびまわり」という部分の意味です。</p> <pre class="code" data-lang="" data-unlink>今日も 下手したら 同じところを周ってばかりで 明日できるさ 帰納法によれば成り立たぬ</pre> <p>得てして長時間の割り込み禁止が発生してしまうのはバグの存在を意味します。というのも、先ほど説明した通り、長時間の割り込み禁止は様々な問題を引き起こす可能性があるため、そのような状況が発生しないように気をつけてコードを書く責任が開発者にはあるからです。</p> <p>そもそも、アプリケーションレベルでは、割り込みを禁止することは一般に許可されていません。OSのみが割り込みに関連する制御を行うことができるよう、CPUの保護機構を活用して制限をかけている場合がほとんどです。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E6%A1%BC%A5%B6%A1%BC%A5%E2%A1%BC%A5%C9">ユーザーモード</a>・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>モード・特権命令 等々で調べてみてください。)</p> <p>したがって、この種のバグは、OS側で処理が無限ループするなどの要因で発生していることが考えられます。これを描いたのが「今日も 下手したら 同じところを周ってばかりで」という部分です。</p> <p>これを日常生活における類推に落とし込むと「明日から本気出す」などの、問題を先送りにする場面が想像できます。(耳が痛いです…。)</p> <p>残念ながら「明日になればできる」と考えているときは、永遠に来ない相対的な「明日」に対して問題の先送りを繰り返し、目標が達成されないか、達成されたとしても非常に長い時間がかかることが経験上知られています。</p> <p>このように、いくつかの事実から一般的な規則を導く手法を枚挙的<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A2%C7%BC%CB%A1">帰納法</a>といいます。ただ、枚挙的<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A2%C7%BC%CB%A1">帰納法</a>は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%F4%B3%D8%C5%AA%B5%A2%C7%BC%CB%A1">数学的帰納法</a>とは異なり、導かれた規則が正しいとは限りません。(ということで希望を失わずにがんばりましょう!)</p> <pre class="code" data-lang="" data-unlink>やりたいことばかりで リソース不足まっしぐらなの コンテキストスイッチだけで 手一杯だよ</pre> <p>これ…ほんとこれなんですよ。</p> <p>時間は有限な資源です。それはOSにおいても同様です。 CPUのコア一つ一つは、単純な操作を繰り返しているに過ぎず、同時に複数の処理を行うことができません。 そのため、並行して処理を進めるためには、何らかの工夫をする必要があります。 複数のコアを利用して処理を進める並列計算はひとつの手段ですが、それでもコア数分しか並行に演算を行うことができません。 そこで、ほとんどの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%DA%A5%EC%A1%BC%A5%C6%A5%A3%A5%F3%A5%B0%A5%B7%A5%B9%A5%C6%A5%E0">オペレーティングシステム</a>では、あるコアの上で実行されるアプリケーションを短い時間間隔(これをタイムスライスといいます)で切り替えることにより、大局的にみれば複数のアプリケーションが並行して動作しているようにみせる機能を有しています。これを、マルチタスキングといいます。</p> <p>あるCPU上で実行されているアプリケーションを別のアプリケーションに切り替える際には、現在のCPUの内部状態の一部(CPUコンテキスト)を保存してあげる必要があります。この作業を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>といいます。 より具体的には、CPUの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>に入っている値を、各プロセスごとに別々に用意されたメモリ領域にコピーして退避するなどの処理を行なっています。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>もCPU上で実行されるプログラムにすぎませんから、その処理には一定の時間がかかります。</p> <p>ここまでくれば、もう察しの良い方は気づいているかもしれません…そうです、もしも非常に多くのアプリケーションを単一のマシン上で実行しようとすると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>にかかる時間が非常に大きくなり、さらには各アプリケーションが実行される頻度もどんどん下がってゆくことになります。つまり、アプリケーションの処理がほとんど進まなくなってしまう可能性があるわけです。これを飢餓状態(resource starvation)といいます。</p> <p>…ですから、やりたいこと(アプリケーション)の数が多すぎるとリソース(資源、ここではCPU時間)不足に陥り、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>だけでCPU時間を食い尽くす飢餓状態になる、ということです。</p> <p>みなさんもやりたいことスタックの大きさには気をつけておきましょう。(耳が痛いです…。)</p> <pre class="code" data-lang="" data-unlink>ぐーるぐるぐる回る run queue このスケジューラーは壊れてる panic 寸前のシステムを 救えるのは君だけさ ほらね</pre> <p>さて、前項で説明した<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>を司るのは、OSの中でもスケジューラーと呼ばれる部分になります。スケジューラーは、実行可能だが現在CPU上では実行されていないタスクの一覧をrun queueとよばれるデータ構造に保持しており、その中から次に実行すべきタスクを選択して、そのプロセスに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>を行うことで、タスクを順々に実行していきます。(ちなみにここではアプリケーション・プロセス・・タスクという用語が入り乱れていますが、これらの厳密な定義はOSの実装に依存しますので、まあとにかく「処理の管理単位」なんだなあ、と思っていただければ助かります。)</p> <p>実を言うと近年のほとんどのOSでは、タスクごとの優先度やリアルタイムタスクの実行などを考慮するために、単純なqueueを用いてスケジューラーが実装されているわけではないのですが、シンプルなモデルとしてここではqueueで考えることにします。</p> <p>queueの中には実行を待っているタスクが入っており、OSはそれらを順番に取り出してCPUに割り当ててゆくことで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%EB%A5%C1%A5%BF%A5%B9%A5%AF">マルチタスク</a>を実現するので、まるでタスクがキューの中をぐるぐる回っているかのような感じになります。</p> <p>もしもスケジューラーにバグがあったら、あるプログラムが永遠に実行されなかったり、色々困ったことが起きるかもしれません。下手をすると、システムの動作に必要なプロセスまでもがいつまでも実行されず、OSが固まってしまう、ということもあるかもしれません。そういった、OSにとって重大な問題が発生して、回復できる見込みがない場合は、OSはエラーメッセージを出力して再起動します。これをpanicと呼ぶことがあります。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>でいえば<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D6%A5%EB%A1%BC%A5%B9%A5%AF%A5%EA%A1%BC%A5%F3">ブルースクリーン</a>のようなものです。)</p> <p>panicが発生するようなギリギリの状態にOSがある際は、十中八九割り込みが禁止されています。このような状況下では、キーボード割り込みなどの通常の割り込みは受け付けられません。</p> <p>でも、こんなときでもなんとかなる割り込みが実はあるのです。</p> <pre class="code" data-lang="" data-unlink>すいみん睡眠preparation 最高優先度でよろしくね すいみん睡眠preparation 問答無用で割り込むよ すいみん睡眠preparation これは無視不可能なシグナル すいみん睡眠preparation いますぐおふとんへIRET</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/x86">x86</a>には、NMIという割り込みがあります。これは、Non-Maskable Interruptの略で、CPUでたとえ割り込みを禁止していたとしても、この割り込みに関しては即座に処理が行われる、という特別な割り込みです。(実は<a class="keyword" href="http://d.hatena.ne.jp/keyword/AMD">AMD</a>のハイパーバイザまわりの文脈ではNMIをマスクできるとかいうNMIのアイデンディティ崩壊級の面白い話があったりするのですがそこらへんは一旦忘れましょう。)当然、この割り込みは、あらゆる割り込みに優先して(他の割り込み処理を実行中でも関係なく)処理が行われます。つまり、無視できないシグナルなわけです。</p> <p>みなさんが何かの作業に熱中し過ぎている時には、きっと割り込みは無効化されているのでしょう。たとえば、宅配便が届いてインターホンが鳴っても気づかなかったり、呼びかけられても気づけなかったりするのがその一例です。</p> <p>しかし、時には何よりも優先して実行すべきことがあるケースがあります。それが睡眠です(要出典)。というかそうしたいですね。難しいですが。</p> <p>言い換えれば、我々の生活の健全性を担保するためには「マスク不可能な、おふとんへ今すぐ行け割り込み」が必要なわけです。</p> <p>で、IRETというのは、RETurn from Interrtuptという命令で、割り込み処理を終了し、割り込みが起こった際に実行されていたコードの実行を再開するという命令です。 この命令は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>でも利用されているので、まあ「マスク不可能な、おふとんへ今すぐ行け割り込み」が発生したら、熱中していたタスクから一旦<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C6%A5%AD%A5%B9%A5%C8%A5%B9%A5%A4%A5%C3%A5%C1">コンテキストスイッチ</a>して、睡眠プロセスへ切り替えるというのが重要ですよ、という話をここでしています。</p> <pre class="code" data-lang="" data-unlink>たまにどうしても 無理なときは 仕方ないから 全部吐き出して 今度直せばいいのさ 次はもっとうまくやれるはず</pre> <p>まあ、無事におふとんへ辿り着けたらいいわけですが、ときには睡眠失敗するケースもあります。そういうときはまあpanicするしかないわけですが、panicする際は、後でなぜpanicしたのか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>できるように、メモリの状態をダンプすることがあります。これをコアダンプと言います。また、コアダンプを「吐く」とか「吐かせる」という慣用表現があり(dumpなので)、つまるところどうしても眠れないなら、現在のメモリの状態(頭の中のもやもや)を全部紙かなんかに書き出して、次の修正の参考にするといいよ、ってことを言ってます。</p> <p>プログラムに完璧はありません。常にバグがあります。なので、コアダンプは大事です。失敗しないことよりも、次の失敗を防ぐ方法をつくること、そしてその<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>を容易にする仕組みを用意することが重要です。</p> <pre class="code" data-lang="" data-unlink>だから すいみん睡眠preparation 入出力は一時停止で すいみん睡眠preparation 机の上を片付けようね すいみん睡眠preparation 頭の中身書き残したら すいみん睡眠preparation おやすみ世界</pre> <p>こっちは正常系の話で、suspend to diskの処理を表現しています。 よく、コンピューターにおけるメモリは、作業をするための机として例えられます。机が広ければよりたくさんのことを同時に効率よくできる、というアナロ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B8%A1%BC">ジー</a>から来ているのでしょう。 さて、コンピューターがsuspendする際には、電力消費を抑えるために、メインメモリの内容をディスクなどの不揮発性の記憶装置に書き出します。(メモリが不揮発性とは限らないよ!NVDIMMがあるよ!と叫んでいる私のことは無視してください。)というのも、通常のコンピューターのメインメモリとして利用されている<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%B2%D9">電荷</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%C7%A5%F3%A5%B5">コンデンサ</a>にためるような感じでデータを保持しており、その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%C5%B2%D9">電荷</a>は時間経過で抜けてしまうため、定期的にデータを読み出して再度書き込むという操作(リフレッシュ)を行う必要があり、継続的に電力を消費するため、ここにデータを置いたままにしておくのは不都合だからです。</p> <p>とはいえ、OSのほとんどの状態はメモリ上にありますから、OSが必要な処理、たとえば入出力装置とのやりとりなどがsuspend処理中に起こるとよろしくありません。というわけで、一般的にコンピューターをsuspendする場合には、アプリケーションの動作を停止し、さらに入出力装置を一旦止め、そしてメモリの内容をディスクに書き出し、電源を落とす、という処理になります。</p> <p>みなさんが睡眠の準備をする際も、うっかり<a class="keyword" href="http://d.hatena.ne.jp/keyword/SNS">SNS</a>などを見て割り込み処理が発生してしまうと、睡眠失敗panic路線まっしぐらになる可能性が高いです。というわけで、この順序を守って、安全にシステムをsuspendするようにしましょう。</p> <p>ということで、おやすみなさい!よい夢を!</p> hikalium 光造形3Dプリンターはじめてみた(ELEGOO Mars 2 Pro) hatenablog://entry/13574176438049762788 2022-01-05T23:00:59+09:00 2022-01-05T23:00:59+09:00 きっかけ 3Dプリンタ欲しさが増している(自作キーボード改造に使いたさがある)— hikalium (@hikalium) 2022年1月1日 この前の記事で、私もついに自作キーボードに足を踏み入れたわけですが、keyball46の個人的につらいポイントとして、キーがとても少ないというのが挙げられます。 というのも、私はこれまでErgoDox EZを使用していたため、キーの数が十二分にあるような環境に慣れすぎており、さすがにキーの数が76から46に激減するとかなりの厳しさを感じます。(もちろん慣れの問題だとは思いますが。) せめて、親指あたりにもう数キーくらい欲しいところです。 さて、実はke… <h1>きっかけ</h1> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>欲しさが増している(自作キーボード改造に使いたさがある)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1477287553711878144?ref_src=twsrc%5Etfw">2022年1月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a href="https://hikalium.hatenablog.jp/entry/2021/12/31/150738">この前の記事</a>で、私もついに自作キーボードに足を踏み入れたわけですが、keyball46の個人的につらいポイントとして、キーがとても少ないというのが挙げられます。 というのも、私はこれまでErgoDox EZを使用していたため、キーの数が十二分にあるような環境に慣れすぎており、さすがにキーの数が76から46に激減するとかなりの厳しさを感じます。(もちろん慣れの問題だとは思いますが。)</p> <p>せめて、親指あたりにもう数キーくらい欲しいところです。</p> <p>さて、実はkeyball46をよく見てみると、キーマトリクス的には左右それぞれ6*4=24キーの合計48キーに対応できるはずなのに、左右共に1キーずつ不足していることに気づくはずです。</p> <p><figure class="figure-image figure-image-fotolife" title="実はそれぞれもう1キーずつサポートできる余裕がありそう"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105211520.png" alt="f:id:hikalium:20220105211520p:plain" width="1200" height="511" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>実はそれぞれもう1キーずつサポートできる余裕がありそう</figcaption></figure></p> <p>この不足しているキーに対応する接点は、keyball46のオリジナルのファームウエアでは、キーボードの左右を自動で検出するためのジャンパ代わりに利用されています。</p> <p><figure class="figure-image figure-image-fotolife" title="SWと書かれている接点(中央左下)が、欠けているキーにあたる"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105211737.jpg" alt="f:id:hikalium:20220105211737j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>SWと書かれている接点(中央左下)が、欠けているキーにあたる</figcaption></figure></p> <p>ですが、私は自前でファームウエアを書いたので、これらの接点はただ「どこにもつながっていない幻のキー」になっているだけなのです。かなしいですね。</p> <p>…ということは、ここにスイッチを生やしたらもう1キーずつ手に入れられるのでは?</p> <p>そう思った私は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>を買うことにしました(論理の飛躍が激しい)</p> <h1>買ったもの</h1> <p>数時間ネットの海をさまよった結果、<a href="https://www.elegoo.com/products/elegoo-mars-2-pro-mono-lcd-3d-printer">ELEGOO MARS PRO 2</a>という光造形方式の<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>を<a href="https://www.amazon.co.jp/gp/product/B08F7LZQV9?th=1">Amazon</a>から34999円で購入しました。</p> <p>また、光造形<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>は、紫外線を当てると液体から固体に変化するUVレジンというものを使用して物体を出力します。これには通常のレジンと水洗いレジンの2種類が大きく存在し、通常のレジンは印刷後にアルコール系の溶剤で余剰レジンを洗浄する必要があるのですが、水洗いレジンだと水で同じことができるため便利らしいと聞き、<a href="https://skhonpo.com/products/sk-waterwashableresin">SK水洗いレジン</a>という商品を購入しました。これは<a href="https://www.amazon.co.jp/gp/product/B08LPF6XFN">Amazonで1000ml</a>が6980円]でした。</p> <p>これだけあれば印刷自体はできるようになりますが、色々作業をするときに下に敷くバットだったり、洗浄時に使うタッパーだったり、掃除につかうペーパータオルとかアルコール<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A5%C3%A5%B7%A5%E5">ティッシュ</a>とかも買っておくといいみたいです。他にも、二次硬化という、印刷後の物体を乾燥させた後に、より十分に固化させるために紫外線を当てる手順も場合によっては行われるので、そのための器具が色々販売されていますが、最悪太陽光に当てれば紫外線はタダで手に入りますし、必要になったらそのときに購入すればいいかなと思って、ひとまず私は最初の時点では購入しませんでした。</p> <p>さらに、マスクやゴム手袋・ビニール手袋などの保護具もそろえておく必要があります。(上記の水洗いレジンはそこまで匂いはきつくないですが、それでもある程度は吸ったり触れたりすると有害なはずですので、忘れずに準備しましょう。)</p> <p>あとは、使用後のレジンを濾過するための、ろうととか濾紙とか、濾過したレジンを入れるふ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%BF%A4%C4%A4%AD">たつき</a>の容器とかあるといいかもしれないです。(私は一通りやってから必要だと学んだのでポチりました。)</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%AB%C9%F5">開封</a>からはじめての印刷まで</h1> <p>とりあえず、適当な場所に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%AB%C9%F5">開封</a>して設置してみた図がこれです。</p> <p><figure class="figure-image figure-image-fotolife" title="設置完了した図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105213719.jpg" alt="f:id:hikalium:20220105213719j:plain" width="900" height="1200" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>設置完了した図</figcaption></figure></p> <p>組み立てる必要のある部分はほんの僅かで、基本的にはレジンを入れるタンクを紫外線を発するスクリーンの上にのせて、印刷物をくっつけて引っ張るプラットフォームを取り付けてあげるだけです。</p> <p>ただ、この「プラットフォームを取り付ける」というステップが結構重要で、しかも取扱説明書の方法だとうまくやるのが難しいです。</p> <p>ネットで調べたところ、手順としては</p> <ol> <li>レジンタンクをスクリーンの上におく</li> <li>プラットフォームの角度調整ネジ(六角レンチで回す2ヶ所のやつ)をゆるめる(手で回す固定ネジ自体はこの段階できっちり締めておく)</li> <li>プラットフォームを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DB%A1%BC%A5%E0%A5%DD%A5%B8%A5%B7%A5%E7%A5%F3">ホームポジション</a>に移動するボタンを押して下げる(大まかな向きはこの段階で合わせておく)</li> <li>プラットフォームの上下を微調整して、トレイの底≒スクリーンに密着するようにする</li> <li>角度調整ネジを動かない程度にそっと締めて、Z=0をこの位置で設定する</li> <li>少しプラットフォームを上げてから、ネジを本締めする(ネジを締める力でスクリーンが割れないようにするために浮かせている)</li> </ol> <p>みたいな感じで調節するといいみたいです。(要するに、プラットフォームがZ=0にあるときに、スクリーンに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%DC%BF%A8">接触</a>している必要があるわけです。)</p> <p>そんなわけで、付属している<a class="keyword" href="http://d.hatena.ne.jp/keyword/USB%A5%E1%A5%E2%A5%EA">USBメモリ</a>をプリンタに挿して、ファイルを選択し(なんと説明書に書いてある拡張子とは違うやつを選ぶ必要があった…モデルのプレビューが表示されるファイルが印刷できるやつです(<code>.ctb</code>ファイル))、あとは待っていると…</p> <p><figure class="figure-image figure-image-fotolife" title="印刷途中のようす(液体から固体ができあがってくるの、見てて楽しい)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105214914.jpg" alt="f:id:hikalium:20220105214914j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>印刷途中のようす(液体から固体ができあがってくるの、見てて楽しい)</figcaption></figure></p> <p>こんな感じで生えてきます。(うまくいっていると、各層の露光が終わってプラットフォームが上がる時に、軽く「ペリペリッ」って音がします。これは、レジンタンクの底から、固化したレジンが剥がれて、プラットフォームの側についている証拠なので、これが聞こえたら成功の望みが高めな気がします。(必要条件でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%BD%CA%AC%BE%F2%B7%EF">十分条件</a>でもないですが。))</p> <p>さらに部屋を片付けつつ2時間37分くらい待つと、こんなかんじで出来上がります。</p> <p><figure class="figure-image figure-image-fotolife" title="2h37mで完成!(想像より早かった)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105215154.jpg" alt="f:id:hikalium:20220105215154j:plain" width="900" height="1200" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>2h37mで完成!(想像より早かった)</figcaption></figure></p> <p>出来上がった物体はプラットフォームにくっついているので、これを同封されていたヘラで剥がします。</p> <p>最初、力加減がわからなくて戦々恐々としていたのですが、プラットフォームは金属でできているので、プラットフォームの面を垂直にしてバットなどの上におき、同封されていた金属製のヘラをその面に添わせて印刷物の底を「えいやっ!」って何回か叩くと取れました。(ヘラとプラットフォームが削れてできた汚れが印刷物に若干ついてしまったが、まあ許容範囲でしょう。印刷物は印刷完了直後の段階ですでに結構硬いので、そこまで手加減しなくても大丈夫みたいです。)</p> <p><figure class="figure-image figure-image-fotolife" title="印刷物をプラットフォームから取り外した様子(最初はけっこう難儀した)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105215526.jpg" alt="f:id:hikalium:20220105215526j:plain" width="900" height="1200" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>印刷物をプラットフォームから取り外した様子(最初はけっこう難儀した)</figcaption></figure></p> <p>あとは適当な大きめの容器に水をいれて、そこに印刷物をいれて余剰レジンを洗い流し、ペーパータオルで拭けば完成です。わーい!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">え、クオリティ高いな…すごい…(はじめての<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF%A1%BC">3Dプリンター</a>体験) <a href="https://t.co/LYSbwTaMoV">pic.twitter.com/LYSbwTaMoV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1478295834710388743?ref_src=twsrc%5Etfw">2022年1月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>あとかたづけ系のTips</h1> <p>印刷後にどう片付ければ/次回の印刷の準備をすればいいのか、いまいち体系的な解説がなかったので、色々調べた結果私がやったことを書いておきます。</p> <ul> <li>プラットフォームに残っている固化したレジンは金属のヘラで綺麗に除去し、アルコール<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A5%C3%A5%B7%A5%E5">ティッシュ</a>などで汚れをとる <ul> <li>固形物が残っていると、プラットフォームが十分に下がらずスクリーンに密着しないので、最初の層がうまく生成されない原因になる</li> </ul> </li> <li>印刷に失敗した場合は、固化したレジンがレジンタンクの底のフィルム(つまりスクリーン側)に付着しているので、レジンタンクの底のフィルムやディスプレイを破壊しないように手やプラスチックのヘラでそっと除去する <ul> <li>プリンターについているクリーニング機能を使うと楽。 <ul> <li>これは、印刷面全体に紫外線を短時間(デフォルト15秒)照射することで、レジンタンクの底にきれいに1層固体化したレジンを生成してくれるので、それを剥がせばOKという機能。</li> <li>底に生成されたレジンの層をはがすために、適当にまあまあ丈夫な紙の切れ端とかを先にレジンタンクの底に触れるように入れてから、クリーニング機能の照射を行い、紙切れをひっぱりだすと、ペリペリと剥がれてくれる(たのしい)</li> </ul> </li> <li>他の方法としては、固化したレジンは1層だけでも意外と硬いので、レジンタンクを外して下側から指で押してフィルムを少したわませてあげると、ぺりっと剥がれてくれる。 <ul> <li>ただし、このときレジンタンクの外側にレジンがつかないように気をつけたほうがよい。そうしないと、レジンがスクリーンに付着して、それが次の印刷時に固化して取れなくなってしまう。そうなったらthe endなので、再度レジンタンクを設置する前にアルコール<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C6%A5%A3%A5%C3%A5%B7%A5%E5">ティッシュ</a>などできれいにふいておいたほうがよさそう。</li> </ul> </li> </ul> </li> <li>印刷に失敗したりして、固化したレジンが混ざってしまったりしたときや、しばらく(1週間くらい?)印刷しないときは、一旦中身を全部外に出して、ろうとで濾過する。 <ul> <li>紫外線に当てなければ固化しないので、少しの間使わないくらいならそのまま放置でも大丈夫そう?(未検証)</li> </ul> </li> <li>洗浄に使った水は、太陽光に当てるなどしてレジンを固化してから、固形物を濾過して除去し、残りの液は下水に流せばよいみたいです。固形物は燃えないゴミみたい。(レジンの取扱説明をよく読みましょう。)</li> </ul> <h1>3Dデータ作成Tips</h1> <p>適当に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>でモデルをつくってexportする際にいくつかハマりポイントがあったのでそれについてもメモ。</p> <ul> <li>最初に<a href="https://docs.blender.org/manual/en/latest/scene_layout/scene/properties.html#units">Scene propertyのUnit scale</a>を0.001に設定しておく。こうしておかないと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>上と実際の印刷時の縮尺がずれる。逆に言えば、これを設定しておけば<a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>内でcmとかの単位で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E2%A5%C7%A5%EA%A5%F3%A5%B0">モデリング</a>すれば、それがそのまま出力される。</li> </ul> <p><figure class="figure-image figure-image-fotolife" title="BlenderのScene propertyの設定"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105222505.png" alt="f:id:hikalium:20220105222505p:plain" width="1200" height="674" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>のScene propertyの設定</figcaption></figure></p> <ul> <li><p>エクスポート時は<a class="keyword" href="http://d.hatena.ne.jp/keyword/STL">STL</a>形式を選ぶ。スケールはさっき設定したので、デフォルトの1.0で大丈夫。他のプロパティもデフォルトでOK。Apply ModifiersをOnにしておけば、ちゃんとModifierが適用された後のモデルが出力されるので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>上でModifierをApplyしておかなくても大丈夫なので便利。Selection Onlyにチェックを入れれば、選択したObjectだけを書き出せるので便利。</p></li> <li><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>上でのマイナスZ方向が、印刷時にプラットフォームに接する側になる。(もちろん、CHITUBOXでも回転はできるので後で修正もできるが、最初から合わせておくと楽。)</p></li> <li><p>サポートをつけて印刷するの、むずかしい。接地面が小さいobjectを印刷するのは難しい。</p></li> <li><p>でも上の図みたいな平面は割と簡単に出せる。Z軸方向に薄いオブジェクトだと印刷もはやい。</p></li> </ul> <p><figure class="figure-image figure-image-fotolife" title="適当にBlenderでつくったモデル(test.blend)の出力結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105223357.jpg" alt="f:id:hikalium:20220105223357j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>適当に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Blender">Blender</a>でつくったモデル(test.blend)の出力結果</figcaption></figure></p> <ul> <li>印刷物をプラットフォームから剥がしやすいように、モデルの接地面側に隙間をつくっておくと楽かも?(test.blendでは角をひとつ隙間があくようにカットしたところ、かなり楽に外せたのでよかった。)</li> </ul> <p>3Dデータをスライスして3Dプリント可能にするCHITUBOXというソフトの注意点</p> <ul> <li>プリンタのプロファイル設定はちゃんとしましょう(最初忘れててよくわからなくなった) <ul> <li>ファイル形式もどうやらプロファイル設定に依存して自動で変わるみたい</li> <li>とりあえずデフォルト設定でふつうに簡単なモデル(上に示したtest.blendのようなもの)なら印刷できた</li> </ul> </li> <li>接地面が小さいと難易度が上がるのでがんばりましょう(サポートを生やすなどの工夫が必要みたいだが私の鍛錬が足りないのでまだ印刷には成功していない)</li> </ul> <h1>生成物のクオリティについて</h1> <ul> <li>かなりクオリティは高い。積層痕が全然見えないレベル。サンプルデータのチェスのコマの天面に印刷されている、2mmくらいの大きさの文字もばっちり見えている。</li> <li>使用するレジンにもよるとは思うが、見た目や感触は完全に切り餅みたいな感じ。だが切り餅よりも硬い。(年末年始なのでなおそう見える(なお私は今季まだ一度も餅を食べていない…。))</li> <li>出力された物体はかなり硬い。厚さ6mmもあれば全くしならない。</li> <li>精度もかなり高い。test.blendにはキースイッチがはまる穴をあけたが、ふつうに綺麗にはまって衝撃を受けた。(乾燥や時間が経つにつれて収縮はあるかもしれないが、未確認。) <ul> <li>ただし、最初の層は他の層にくらべて硬く、さらに多少XY平面方向に太る。各方向に0.1~0.2mmくらい。これは初期層は他の層にくらべて露光時間が長く設定されているためである。</li> </ul> </li> </ul> <p><figure class="figure-image figure-image-fotolife" title="キースイッチをはめてみた図。引っ張るとキーキャップの方が先にとれるレベルでしっかりはまっている。"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20220105/20220105225053.jpg" alt="f:id:hikalium:20220105225053j:plain" width="1200" height="898" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>キースイッチをはめてみた図。引っ張るとキーキャップの方が先にとれるレベルでしっかりはまっている。</figcaption></figure></p> <h1>まとめ</h1> <p>もっと早く買えばよかった。みんなも<a class="keyword" href="http://d.hatena.ne.jp/keyword/3D%A5%D7%A5%EA%A5%F3%A5%BF">3Dプリンタ</a>を買ってあそぼう!</p> hikalium 2021年の振り返り hatenablog://entry/13574176438048071755 2021-12-31T19:35:31+09:00 2021-12-31T19:40:52+09:00 今年は何があったかを振り返ってまとめておく。 1月 やっとNoogler Hat (物理)が届いた やっとNoogler Hat(物理)が届いた!(なおNoogler(新入社員)期間は3ヶ月前に終わっているはず…いや、まだ始まっていないのか!?) pic.twitter.com/KpvRladJmc— hikalium (@hikalium) 2021年1月18日 2月 Writing an OS in Rust 輪読会をやっていた(Pagingの回を担当した) 遅くなりましたが、先週月曜日に実施したPaging導入回の録画を公開しました!過去のx86 セグメンテーションの歴史から多段階ページ… <p>今年は何があったかを振り返ってまとめておく。</p> <h1>1月</h1> <p>やっとNoogler Hat (物理)が届いた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">やっとNoogler Hat(物理)が届いた!<br>(なおNoogler(新入社員)期間は3ヶ月前に終わっているはず…いや、まだ始まっていないのか!?) <a href="https://t.co/KpvRladJmc">pic.twitter.com/KpvRladJmc</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1351107906456981505?ref_src=twsrc%5Etfw">2021年1月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>2月</h1> <p>Writing an OS in Rust 輪読会をやっていた(Pagingの回を担当した)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">遅くなりましたが、先週月曜日に実施したPaging導入回の録画を公開しました!過去の<a class="keyword" href="http://d.hatena.ne.jp/keyword/x86">x86</a> セグメンテーションの歴史から多段階ページング、TLBの話まで盛りだくさんなのでぜひ!<a href="https://twitter.com/hashtag/reading_os_in_rust?src=hash&amp;ref_src=twsrc%5Etfw">#reading_os_in_rust</a><br><br>Introduction to Paging - Writing an OS in Rust 輪読会 (by hasimoto) <a href="https://t.co/pbr54BPTgZ">https://t.co/pbr54BPTgZ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1360902469522366467?ref_src=twsrc%5Etfw">2021年2月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>3月</h1> <p>hikalium(物理)をPixivFACTORYで発注したのが届いた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">hikalium(物理)の画像です(物理とは)。 <a href="https://t.co/1Gz32NDJux">pic.twitter.com/1Gz32NDJux</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1373195664356642818?ref_src=twsrc%5Etfw">2021年3月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと前の年にもらっていた賞の賞状が届いた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">昨年頂いた、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BE%F0%CA%F3%BD%E8%CD%FD%B3%D8%B2%F1">情報処理学会</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D4%A5%E5%A1%BC%A5%BF%A5%B5%A5%A4%A5%A8%A5%F3%A5%B9">コンピュータサイエンス</a>領域奨励賞の賞状が忘れた頃になって今日届いた。これは論文書こうねというメッセージなのかもしれない…。 <a href="https://t.co/8hKDOMnzoq">pic.twitter.com/8hKDOMnzoq</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1375012368451702785?ref_src=twsrc%5Etfw">2021年3月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>4月</h1> <p>nekoi7yuさんと一緒に低レイヤ雑談する配信をした</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/I84L4vxua1w?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=I84L4vxua1w">www.youtube.com</a></cite></p> <p>あと私のL2キャッシュ(本棚)が低レイヤすぎて、みんな結構面白がってくれた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">机のすぐ近くにある本棚(通称L2キャッシュ)を拡張したら、なかなか圧の強いラインナップになった。(ここは本屋ではない。) <a href="https://t.co/sGsL4fVwqN">pic.twitter.com/sGsL4fVwqN</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1378371918986809344?ref_src=twsrc%5Etfw">2021年4月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてKOBA789氏と共に、自作<a class="keyword" href="http://d.hatena.ne.jp/keyword/RDBMS">RDBMS</a>を自作OSに移植するコラボ配信をした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">本日のrellyをliumOSに移植する<a href="https://twitter.com/KOBA789?ref_src=twsrc%5Etfw">@KOBA789</a>氏とのコラボ配信の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>はこちらです!(トリミングしたのが反映されるまでは、10:15から再生するといい感じになります。)<br>みなさまよいGW自作生活をお楽しみください!<br><br>自作<a class="keyword" href="http://d.hatena.ne.jp/keyword/RDBMS">RDBMS</a>を自作OSの上で動かしてみよう <a href="https://t.co/1pDrE8sT2l">https://t.co/1pDrE8sT2l</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1388054375185010690?ref_src=twsrc%5Etfw">2021年4月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ダイジェスト版も789氏が作ってくれた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">KOBA789「ところでliumOSって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>あるんですか」<br>hikalium「うっ、あっ、あっ、あっ…<br>いいですねぇ〜」<br>の流れめっちゃ笑った。 <a href="https://t.co/YYGamOoG9b">https://t.co/YYGamOoG9b</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1388818297412411396?ref_src=twsrc%5Etfw">2021年5月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>5月</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>・ラボユース10周年記念の対談記事が公開された。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgihyo.jp%2Fnews%2Finterview%2F2021%2F05%2F1801" title="新規のテーマより“自分が作りたいもの”を ―歴代卒業生とメンターが語る「サイボウズ・ラボユース」10年間の軌跡" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://gihyo.jp/news/interview/2021/05/1801">gihyo.jp</a></cite></p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Software%20Design">Software Design</a>による<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>・ラボユース10周年記念の対談記事です。<br>新規のテーマより“自分が作りたいもの”を ―歴代卒業生とメンターが語る「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>・ラボユース」10年間の軌跡 <a href="https://t.co/cVMeO8AhI2">https://t.co/cVMeO8AhI2</a><a href="https://twitter.com/sinya8282?ref_src=twsrc%5Etfw">@sinya8282</a>, <a href="https://twitter.com/slankdev?ref_src=twsrc%5Etfw">@slankdev</a>, <a href="https://twitter.com/hikalium?ref_src=twsrc%5Etfw">@hikalium</a>さんありがとうございました。Cc: <a href="https://twitter.com/takesako?ref_src=twsrc%5Etfw">@takesako</a>さん</p>&mdash; herumi (@herumi) <a href="https://twitter.com/herumi/status/1394462081177374720?ref_src=twsrc%5Etfw">2021年5月18日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>6月</h1> <p>KAT WALK Cが届いた(これで<a class="keyword" href="http://d.hatena.ne.jp/keyword/VR">VR</a>内で走れる!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんか巨大な物体が届いた(KAT WALK C)。<br>これで、ワイヤードにフルレンジフルモーションでアクセスできるっぽい。<br>(配達の方と「これってなんなんですかね」「ばーちゃるりありてぃ?ってやつです」みたいな謎の会話をした。)<br>ただ私の物理身体が今は不調なので、セットアップは少し先になりそう…。 <a href="https://t.co/3KVNorrRpg">pic.twitter.com/3KVNorrRpg</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1399636801690619905?ref_src=twsrc%5Etfw">2021年6月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>とてもでかいです。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">きれいになった部屋は早速この子で埋め尽くされました(KAT WALK Cを設置した)。 <a href="https://t.co/mCzigtIe6v">pic.twitter.com/mCzigtIe6v</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1401433218058842114?ref_src=twsrc%5Etfw">2021年6月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>の動く<a class="keyword" href="http://d.hatena.ne.jp/keyword/RISC">RISC</a>-Vマシンで少し遊んだ(もっと遊んであげなきゃ…)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">すごい、本当に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>の動く物理riscv64マシンだ…となっています(これは遊べそう)。 <a href="https://t.co/CaJUUjRfSE">pic.twitter.com/CaJUUjRfSE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1400834103658778631?ref_src=twsrc%5Etfw">2021年6月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと人々に<a class="keyword" href="http://d.hatena.ne.jp/keyword/malloc">malloc</a>を実装させるなどしていた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とある授業で使うために作った(というか自分が欲しくて作った)<a class="keyword" href="http://d.hatena.ne.jp/keyword/malloc">malloc</a>のvisualizerが見ていて楽しいのでおすすめ。<a href="https://t.co/Zi4f26aIj0">https://t.co/Zi4f26aIj0</a> <a href="https://t.co/DE1zUm7Bio">pic.twitter.com/DE1zUm7Bio</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1406255772539887626?ref_src=twsrc%5Etfw">2021年6月19日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>7月</h1> <p>hikaliumのファンアートが初めて作成された(うれしかった!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今年のSTEP参加者 <a href="https://twitter.com/Sakuramochi345?ref_src=twsrc%5Etfw">@Sakuramochi345</a> さんによるhikaliumと<a class="keyword" href="http://d.hatena.ne.jp/keyword/malloc">malloc</a>プリンです。ありがとうございます!(髪の色の再現度が高くてめっちゃ感動している…。) <a href="https://t.co/mt0DkE9lMs">pic.twitter.com/mt0DkE9lMs</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1412412474704465937?ref_src=twsrc%5Etfw">2021年7月6日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてさらに<del>散財</del>機材がアップデートされた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">最近目がすぐにだめになるとか呟いていた結果、視覚デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>のアップデートが届いた(?) <a href="https://t.co/PgeQgQiGU9">pic.twitter.com/PgeQgQiGU9</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1414232299344855047?ref_src=twsrc%5Etfw">2021年7月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あとはRasPiと低いレイヤでおはなしして仲良くなった</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2021%2F07%2F18%2F214013" title="Raspberry Pi 4をJTAGデバッグしてみる(FTDI C232HM-DDHSL-0使用) - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2021/07/18/214013">hikalium.hatenablog.jp</a></cite></p> <h1>8月</h1> <p>kurenaifさんにPOODLE Attackを教わった(させていただいた)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">暗号初心者の私でも、POODLE Attackできました!!!<br>(kurenaifさんの分かりやすいヒントがある場合に限る。)<br>ちゃんと動画中でフラグ全体を取れてよかった…。<a href="https://twitter.com/fwarashi?ref_src=twsrc%5Etfw">@fwarashi</a> に感謝!<br><br>【CVE-2014-8730】POODLE Attackをや「ら」せてみた【hikalium x kurenaif】 <a href="https://t.co/qzHqtAYQCr">https://t.co/qzHqtAYQCr</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1421750413074714634?ref_src=twsrc%5Etfw">2021年8月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>FLAGがとれたときの様子</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">hikalium「POOO...DLEっ!!!できたあ〜!!!」<br>kurenaif「おめでとうございます!」<br>のシーンです。(これたのしい。)<br><br>【CVE-2014-8730】POODLE Attackをや「ら」せてみた【hikalium x kurenaif】 <a href="https://t.co/YHs9dnXKnV">https://t.co/YHs9dnXKnV</a> <a href="https://t.co/X8WM1kDxF3">pic.twitter.com/X8WM1kDxF3</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1421752715470774274?ref_src=twsrc%5Etfw">2021年8月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>この時期の作業環境はこんな感じだった</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「私のリモートワーク環境写真展」に投稿してみた。<br><br>たくさんのコンピューターに囲まれながら、大きなディスプレイに映したエディタを、色をアイコンにあわせてカスタマイズした分割キーボードと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>で操作しています。… <a href="https://twitter.com/hashtag/%E7%A7%81%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E7%92%B0%E5%A2%83%E5%86%99%E7%9C%9F%E5%B1%95?src=hash&amp;ref_src=twsrc%5Etfw">#私のリモートワーク環境写真展</a> <a href="https://t.co/aUcznujI7J">https://t.co/aUcznujI7J</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1421782661173891076?ref_src=twsrc%5Etfw">2021年8月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと2回目のセキュリティアップデートをインストールした際のログがこちら</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">まだ頭が痛いけどなにかやりたかったので、モデルナ2回目接種してからの私の物理<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>の心拍数と体温と症状と薬の投入状況をまとめた図を作ってみた(何の役にも立たない図です)(心拍数と体温の傾向が大まかに似ていて、人体面白いですねという気分になった)。 <a href="https://t.co/JwN3lwm6gC">pic.twitter.com/JwN3lwm6gC</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1422778077680046081?ref_src=twsrc%5Etfw">2021年8月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてセキュキャンの時期が近づく…(Tシャツのデザイン決めにほんの少しだけ関わった)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">セキュキャンTシャツ〜の図です(私もちょっとだけ企画に関わったので、想像通りのデザインになっていてうれしい)。<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/ZVbBpaEdnE">pic.twitter.com/ZVbBpaEdnE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1423280416488755205?ref_src=twsrc%5Etfw">2021年8月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>背中の暗号はみなさん解けましたか?</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">背面もちゃんとあるぞ<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/lMx1hm5Qkw">pic.twitter.com/lMx1hm5Qkw</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1423283110024601603?ref_src=twsrc%5Etfw">2021年8月5日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてお仕事で最近やっていたことについて話した。低レイヤな仕事、一緒にやりませんか!</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/p0BfJZU0iE8?start=706&feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=p0BfJZU0iE8&t=706s">www.youtube.com</a></cite></p> <p>スライドはここから辿れます。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日の <a href="https://twitter.com/hashtag/osc21aizu?src=hash&amp;ref_src=twsrc%5Etfw">#osc21aizu</a> で発表したスライドです! ChromeOSの上で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Android">Android</a>が動く話について書かれたものはそんなに多くないと思うので、大雑把ではありますが、もし興味があれば発表の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>と共に見てみてください!<br>(そして東京で低レイヤなお仕事の募集もあるのでぜひ!)<a href="https://t.co/iqkVomp3Jj">https://t.co/iqkVomp3Jj</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1431876716880748546?ref_src=twsrc%5Etfw">2021年8月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あと、WebMIDI経由でnanoKONTROL2と戯れたりもしていた。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">LEDも制御できるようになった(Current Scene Data Dumpメッセージを送ってLED ModeをExternalにしたりする必要があってちょっと面倒だったが、わかれば簡単だった)。<br>公式でspecのテキストファイルがあるので助かる。<a href="https://t.co/qrB8jmGeG3">https://t.co/qrB8jmGeG3</a> <a href="https://t.co/4H6n0HFGaM">pic.twitter.com/4H6n0HFGaM</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1432389531534172166?ref_src=twsrc%5Etfw">2021年8月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>9月</h1> <p>hikaliumロゴアクリルキーホルダーの試作品が届いた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">簡単にhikaliumをインストールできるソリューションが届いた(アクリルキーホルダーとアクリルバッジ)(一体どこに需要があるのか)。 <a href="https://t.co/RgUc9ZVM1l">pic.twitter.com/RgUc9ZVM1l</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1432721175579344913?ref_src=twsrc%5Etfw">2021年8月31日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>なんとここから買えます(この記事執筆現在、8個くらい売れていて驚きました)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">昨日のhikaliumキーホルダー、需要があるっぽいので一応販売に出してみた。<br>一個1000円なので買う人はそんなにいないでしょう…。<br><br>hikaliumキーホルダー | hikalium <a href="https://t.co/CsLBjezJbn">https://t.co/CsLBjezJbn</a> <a href="https://twitter.com/hashtag/booth_pm?src=hash&amp;ref_src=twsrc%5Etfw">#booth_pm</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1433037224388354053?ref_src=twsrc%5Etfw">2021年9月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>セキュキャンのOS自作ゼミでポインタについて熱く語るなどの社会貢献をおこなった(?)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">えーっと、セキュキャンOS自作ゼミだったはずがC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミ並のポインタ談義をしたら日付越えた。(下の画像は説明中に書き換えたりしたので不正確な部分もあるが、要するに<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>のポインタまわりはタノシイ!) <a href="https://t.co/1xAwqir5cm">pic.twitter.com/1xAwqir5cm</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1438519561909792781?ref_src=twsrc%5Etfw">2021年9月16日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてついに低レイヤーガールチャンネルの収益化が承認された!(ありがとうございます!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">おおっ、ついに低レイヤーガールのチャンネルの収益化が承認されていた!<br>まだどうするかは完全に未定ですが、これからも人々と一緒にゆるりとやっていきますので、よろしくお願いします〜<a href="https://t.co/E3YosurZWT">https://t.co/E3YosurZWT</a> <a href="https://t.co/5uVs7TbQyZ">pic.twitter.com/5uVs7TbQyZ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1440547407075299335?ref_src=twsrc%5Etfw">2021年9月22日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>あとInfraStudyという勉強会で、人々を低レイヤーへ誘い込むオタク早口<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>をした</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/j-rAGNokNRU?start=1215&feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=j-rAGNokNRU&t=1215s">www.youtube.com</a></cite></p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/InfraStudy?src=hash&amp;ref_src=twsrc%5Etfw">#InfraStudy</a> 見てくださった皆様、ありがとうございました!低レイヤ、どんどんやっていきましょう!!!<br><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>もありますので、見逃した方もぜひ!<br>(はじめてのスパチャもいただきました!感謝です!)<br><br>Infra Study 2nd #5「低レイヤーの世界への誘い」 <a href="https://t.co/4vJuah8XXF">https://t.co/4vJuah8XXF</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1442841798976569347?ref_src=twsrc%5Etfw">2021年9月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>10月</h1> <p>語り得ぬものについては沈黙せねばならない。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日はもうおしまい。<br>正解に辿り着いた友人に敬意を。</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1446011653997219842?ref_src=twsrc%5Etfw">2021年10月7日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>童心に返ってスライムをmake (smileではない)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">$ make slime <a href="https://t.co/fBXM7PsMeK">pic.twitter.com/fBXM7PsMeK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1448633651663552512?ref_src=twsrc%5Etfw">2021年10月14日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>がんばったので昇進して「(ふつうの)Software Engineer」になりました。(入社から約1年半でなので、まあまあ早いほう。)</p> <p>お給料結構上がってびっくりした。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">レベルアップしてお給料が増えた!わーい!<br>(よくがんばった…!)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1451113274557153282?ref_src=twsrc%5Etfw">2021年10月21日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>はおしまいです(?)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">セリフをつけたら圧が高まった… <a href="https://t.co/QdbmRmengw">pic.twitter.com/QdbmRmengw</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1452704717637763073?ref_src=twsrc%5Etfw">2021年10月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/JINS">JINS</a> MEMEというIoTメガネで遊び始めた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Another new gear...<a href="https://twitter.com/hashtag/JINSMEME?src=hash&amp;ref_src=twsrc%5Etfw">#JINSMEME</a> <a href="https://t.co/ijQow8yTJ7">pic.twitter.com/ijQow8yTJ7</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1453308702560165888?ref_src=twsrc%5Etfw">2021年10月27日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そしてついに、ついに、1年半のおあずけを経て、健康を享受しはじめた!</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">社食で健康を享受している…! <a href="https://t.co/YPMNEAItV1">pic.twitter.com/YPMNEAItV1</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1453929525243383816?ref_src=twsrc%5Etfw">2021年10月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%ED%A5%A6%A5%A3%A1%BC%A5%F3">ハロウィーン</a>も低レイヤでした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">配信終わりました!今日は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%ED%A5%A6%A5%A3%A1%BC%A5%F3">ハロウィーン</a>仕様のhikaliumが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UEFI">UEFI</a>から取得したメモリマップを使って、めちゃくちゃ単純なGlobalAllocatorを実装してRustのallocクレートを使えるようにしました。<br><br>自作OSを拡張する作業配信 - allocクレートを使えるようにする <a href="https://t.co/p7L3103IbF">https://t.co/p7L3103IbF</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より <a href="https://t.co/tZrxfc8jak">pic.twitter.com/tZrxfc8jak</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1454437961479573504?ref_src=twsrc%5Etfw">2021年10月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>11月</h1> <p>789氏の<a class="keyword" href="http://d.hatena.ne.jp/keyword/JINS">JINS</a> MEME hackの結果を再利用させてもらって、hikaliumの頭をぐるぐるさせるなどした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず適当に <a href="https://twitter.com/KOBA789?ref_src=twsrc%5Etfw">@KOBA789</a> 氏の memex のコードを memeliumに取り込んだ結果(<a class="keyword" href="http://d.hatena.ne.jp/keyword/iOS">iOS</a>アプリとかなしで<a class="keyword" href="http://d.hatena.ne.jp/keyword/macbook">macbook</a>単体でJINSMEMEのデータを直接とって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D0%A5%BF%A1%BC">アバター</a>を動かせるのタノシイ!) <a href="https://t.co/JDa9iLhyr1">pic.twitter.com/JDa9iLhyr1</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1465246542982377473?ref_src=twsrc%5Etfw">2021年11月29日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>12月</h1> <p>そしてキーボードが増えた</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">奇遇だ…(私もついさっき鍵盤が来てしまった…でかい) <a href="https://t.co/g8gkyv0Z5F">pic.twitter.com/g8gkyv0Z5F</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1466387515904954376?ref_src=twsrc%5Etfw">2021年12月2日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>PiyoConfというイベントでライブ<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>いじりをしてみた</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/z_J--PMg2_c?start=3870&feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=z_J--PMg2_c&t=3870s">www.youtube.com</a></cite></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/uname">uname</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>を無理やり改造することで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>がPiyoxになったのでした</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日のデモ:<a class="keyword" href="http://d.hatena.ne.jp/keyword/uname">uname</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>を無理やり書き換えて<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>をPiyoxにしてみた(最初<a class="keyword" href="http://d.hatena.ne.jp/keyword/uname">uname</a>がnew_<a class="keyword" href="http://d.hatena.ne.jp/keyword/uname">uname</a>に置き換わってるの気づかなくて焦った)<a href="https://twitter.com/hashtag/PiyoConf?src=hash&amp;ref_src=twsrc%5Etfw">#PiyoConf</a> <a href="https://t.co/6yERisAnpK">pic.twitter.com/6yERisAnpK</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1466986435068981250?ref_src=twsrc%5Etfw">2021年12月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>その余波でスパチャの嵐を受けた…(ありがとうございます!)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">やばい、うんちゃま(<a href="https://twitter.com/tsukkkkkun?ref_src=twsrc%5Etfw">@tsukkkkkun</a>)さんから5000円のスパチャ飛んできた…(みなさんに還元できる形で使わせていただきます…。<br><br>自作ブラウザを拡張する作業配信 - <a class="keyword" href="http://d.hatena.ne.jp/keyword/JavaScript">JavaScript</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A5%D7%A5%EA%A5%BF">インタプリタ</a>をつくる <a href="https://twitter.com/hashtag/low_layer_girls?src=hash&amp;ref_src=twsrc%5Etfw">#low_layer_girls</a> <a href="https://t.co/fGIiSdL64Q">https://t.co/fGIiSdL64Q</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>より <a href="https://t.co/rmzuejxUeP">pic.twitter.com/rmzuejxUeP</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1467100913039212545?ref_src=twsrc%5Etfw">2021年12月4日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ラテアートを作ったり</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">はじめての3Dアートラテ自作入門<br>(おぼれるドロイド君) <a href="https://t.co/tXFm7NfzoB">pic.twitter.com/tXFm7NfzoB</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1470309865348546561?ref_src=twsrc%5Etfw">2021年12月13日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>OS自作の歌を作って歌ったり(生声注意)</p> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/6n-g409s6wo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=6n-g409s6wo">www.youtube.com</a></cite></p> <p>キーボードを作るはずが、買うパーツを間違えたのでRustでファームウエアを書いたりしていた。詳細な顛末は別記事にて。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2021%2F12%2F31%2F150738" title="Keyball46組み立て日記 〜間違えてRP2040を買ったそこのあなたに〜 - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2021/12/31/150738">hikalium.hatenablog.jp</a></cite></p> <h1>通年</h1> <ul> <li><a href="https://www.youtube.com/channel/UCMsstGhINXdpMqo9tsElCMQ">&#x4F4E;&#x30EC;&#x30A4;&#x30E4;&#x30FC;&#x30AC;&#x30FC;&#x30EB; - YouTube</a> <ul> <li>d0iasm氏と一緒に、自作ブラウザとか自作OSをする配信を土曜日に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C4%EA">不定</a>期開催している</li> <li>12/25に、おすすめのコンピューター関連書籍について語り合う配信をしたので、もし興味があればご覧ください!</li> </ul> </li> </ul> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/fiPfe_bQk3I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://youtu.be/fiPfe_bQk3I">youtu.be</a></cite></p> <ul> <li>Writing an OS in Rust 輪読会 <ul> <li><a href="">Writing an OS in Rust</a>という記事をみんなで交代で読んでゆく会。ひとまず掲載されている分の記事はすべてやって<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>が残っているので、興味のある方はぜひ。再生リストは<a href="https://www.youtube.com/playlist?list=PL8U-_gKA4tWtNXVnqYRmn8En5Nh6xzADO">こちら</a>。</li> </ul> </li> </ul> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PL8U-_gKA4tWtNXVnqYRmn8En5Nh6xzADO" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/playlist?list=PL8U-_gKA4tWtNXVnqYRmn8En5Nh6xzADO">www.youtube.com</a></cite></p> <ul> <li><p>Rust <a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> OS Tutorials 輪読会</p> <ul> <li><a href="https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/">Operating System development tutorials in Rust on the Raspberry Pi</a>をみんなで交代でやっていく会。Writing an OS in Rust 輪読会がひと段落したのでその続きとしてやっている。12_integrated_testingまで終わったが、まだ動画を上げきれていない。余裕があったらそのうち<a href="https://www.youtube.com/playlist?list=PL8U-_gKA4tWunzJzVUspqOcOdhDgb1MFW">osdev-jpのチャンネル</a>にアップロードする予定。</li> </ul> </li> <li><p><a href="https://osdev-jp.connpass.com/">自作OSもくもく会</a></p> <ul> <li>osdev-jpとして、uchan_nos氏と一緒に開催している。今年は5回開催された。隔月開催が目標だったので、まあまあといえよう。 発表の録画も発表者の許可があるものについては公開している。(まだアップロードしてないものがあるかも。)</li> </ul> </li> </ul> <p><iframe width="560" height="315" src="https://www.youtube.com/embed/8dxiI3475JY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=8dxiI3475JY">www.youtube.com</a></cite></p> <h1>まとめ</h1> <p>意外と色々やってたんだなあ。えらい!</p> <p>(毎年思っていることだけど)来年はゆっくり過ごしたいと思います…。</p> <p>もっと気楽に生きたいですね。なかなか難しいですが。</p> <p>hikaliumと関わりのあった皆様、今年も大変お世話になりました。来年も、よいお年をお過ごしください!</p> hikalium Keyball46組み立て日記 〜間違えてRP2040を買ったそこのあなたに〜 hatenablog://entry/13574176438047580368 2021-12-31T15:07:38+09:00 2021-12-31T15:26:44+09:00 TL; DR Keyball46はいいぞ ProMicroにはAVR版とRP2040版がある ピン配置の互換性はあれど、命令セットは完全に異なるので「ファームウエアを書けとささやくのよ、私のゴーストが」という方以外はAVR版を間違えずに買いましょう まあ最悪間違えても一週間くらいでなんとかなる(当社調べ) みんな自作キーボードをやろう! はじまり みなさんは、Keyball46という素晴らしい自作キーボードキットをご存知ですか? そう、なんと、キーボードにトラックボールがついてるんです!最高ですよね! ということで、秋葉原にある自作キーボードのお店こと遊舎工房さんから速攻でポチりました。ちょう… <h1>TL; DR</h1> <ul> <li>Keyball46はいいぞ</li> <li>ProMicroにはAVR版とRP2040版がある <ul> <li>ピン配置の互換性はあれど、命令セットは完全に異なるので「ファームウエアを書けとささやくのよ、私のゴーストが」という方以外はAVR版を間違えずに買いましょう</li> </ul> </li> <li>まあ最悪間違えても一週間くらいでなんとかなる(当社調べ)</li> <li>みんな自作キーボードをやろう!</li> </ul> <h2>はじまり</h2> <p>みなさんは、Keyball46という素晴らしい自作キーボードキットをご存知ですか?</p> <p>そう、なんと、キーボードに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>がついてるんです!最高ですよね!</p> <p>ということで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%A9%CD%D5%B8%B6">秋葉原</a>にある自作キーボードのお店こと遊舎工房さんから速攻でポチりました。ちょうど安いキーボードを一個水没させたところですし、自作キーボードも本格的にやりたかったし、年末休みで暇を持て余していますからね。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">役者は揃った。あとは作るだけ…。(キーキャップが想像以上に美味しそうでニヤニヤしている。) <a href="https://t.co/xZM8ZJaWyQ">pic.twitter.com/xZM8ZJaWyQ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1474258864640241667?ref_src=twsrc%5Etfw">2021年12月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>期待に胸を躍らせつつ、はじめての表面実装<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C0%A5%A4%A5%AA%A1%BC%A5%C9">ダイオード</a>のハンダづけを難なくこなし、</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">やっておる(はじめての表面実装) <a href="https://t.co/1j29kwJ8JU">pic.twitter.com/1j29kwJ8JU</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1474279532077416448?ref_src=twsrc%5Etfw">2021年12月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>さて、動作チェックとしゃれこみますか、と思ってファームウエアを焼こうとしたところ、自分の犯したミスに気づきます。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">さて、ここに至ってやらかしに気づきました(ATmega32U4搭載のPro MicroではなくRP2040搭載のPro Microを買ってしまっていた(これはファームウエアを自分で書けという天啓か?)) <a href="https://t.co/YL3Un4njkm">https://t.co/YL3Un4njkm</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1474305693364912133?ref_src=twsrc%5Etfw">2021年12月24日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>はい、パーツを間違えました。ゲームオーバーです。…本当に?</p> <h2>どこで道を踏み外したのか</h2> <p>さて、<a href="https://github.com/Yowkees/keyball/blob/main/keyball46/doc/rev1/buildguide_jp.md#1-2%E7%B5%84%E7%AB%8B%E5%89%8D%E3%81%AB%E3%81%8A%E5%AE%A2%E6%A7%98%E8%87%AA%E8%BA%AB%E3%81%A7%E6%BA%96%E5%82%99%E3%81%84%E3%81%9F%E3%81%A0%E3%81%8F%E9%83%A8%E5%93%81">Keyball46の組み立て説明</a>には、このように書かれていました。</p> <p>(念の為、これは組み立て説明の落ち度ではなく、私の無知が原因です。私が失敗に至るまでの思考過程をお伝えするために引用しており、責任は私にあります。)</p> <blockquote><p>1-2.組立前にお客様自身で準備いただく部品</p> <p>...</p> <p>ProMicro 2個 安価なものやUSB Type-C対応のもの等選べます</p> <p>...</p></blockquote> <p>…なるほど!Pro Microっていう<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>基板を買えばいいのね! 遊舎工房で「Pro Micro」検索、っと…。</p> <p><figure class="figure-image figure-image-fotolife" title="遊舎工房での検索結果(当時)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230144749.png" alt="f:id:hikalium:20211230144749p:plain" width="1041" height="1200" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>遊舎工房での検索結果(当時)</figcaption></figure></p> <p>お、何種類かあるんだ。せっかくだし USB Type-C のがいいなあ、これを買うか!(SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)の商品ページに飛んでカートに入れようとする)</p> <p>(ここでも念を押しておきますが、すべての落ち度は買うものを間違えた私にあります。みなさんは適当にポチらずにきちんと調べてから買いましょう。)</p> <p><figure class="figure-image figure-image-fotolife" title="売り切れ - SparkFun Qwiic Pro Micro - USB-C (ATmega32U4) - 遊舎工房"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230145141.png" alt="f:id:hikalium:20211230145141p:plain" width="1200" height="601" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>売り切れ - SparkFun Qwiic Pro Micro - USB-C (ATmega32U4) - 遊舎工房</figcaption></figure></p> <p>あれ、これは売り切れかあ。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C8%BE%C6%B3%C2%CE">半導体</a>不足の影響もあるのかなあ。じゃあこっちはどうかな?(もう一個の似た見た目のやつをクリック)</p> <p><figure class="figure-image figure-image-fotolife" title="商品がカートに追加されました! - SparkFun Pro Micro - RP2040 - 遊舎工房"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230145337.png" alt="f:id:hikalium:20211230145337p:plain" width="1200" height="641" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>商品がカートに追加されました! - SparkFun Pro Micro - RP2040 - 遊舎工房</figcaption></figure></p> <p>わーい、買えそうだ!これで行こう!楽しみだなあ!!</p> <p>…おわかりいただけただろうか。(ここが運命の分かれ道だった。)</p> <h2>Pro Microの種類</h2> <p>実はPro Microと名のつくボードには、コネクタの形状や互換品か否かという些細な点を除けば、大きく分けて少なくとも2種類が存在します。</p> <ul> <li><a href="https://www.sparkfun.com/products/15795">SparkFun Qwiic Pro Micro - USB-C (ATmega32U4)</a></li> <li><a href="https://www.sparkfun.com/products/18288">SparkFun Pro Micro - RP2040</a></li> </ul> <p>見た目は非常に似ているのですが、何がちがうのかというと、載っている<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>が根本的に違います。</p> <p>前者はATmega32U4, つまりAVR<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>です。 後者は、RP2040…これは<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>と同じ、ARM<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>です。</p> <p>はい、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>て完全に異なりますね。</p> <p>さて、Keyball46が標準で提供しているファームウエアは…</p> <pre class="code" data-lang="" data-unlink># MCU name MCU = atmega32u4 ...</pre> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FYowkees%2Fkeyball%2Fblob%2Fmain%2Fqmk_firmware%2Fkeyboards%2Fkeyball%2Frev1%2Frules.mk%23L2" title="keyball/rules.mk at main · Yowkees/keyball" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/Yowkees/keyball/blob/main/qmk_firmware/keyboards/keyball/rev1/rules.mk#L2">github.com</a></cite></p> <p>はい、ATmega32U4用ですね。おつかれさまでした。</p> <h2>「ファームウエアを書けとささやくのよ、私のゴーストが」</h2> <p>さて、困りましたね。再度ATmega32u4のPro Microを注文するのも時間がかかるだろうし、たとえそうしても、今手元にあるこのRP2040は無駄になってしまいます。それは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>がかわいそうですよね。</p> <p>「…ファームウエアがないなら、書けばいいじゃない!」</p> <p>たしかに!そうしよう!(白目)</p> <h3>方針を考える</h3> <p>とりあえず脳内で盛り上がってるマリーアントワネットと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%F0%C6%E5%C1%C7%BB%D2">草薙素子</a>は放置して、さっさと先に進みましょう。</p> <p>最初はQMK <a class="keyword" href="http://d.hatena.ne.jp/keyword/firmware">firmware</a>をRP2040向けにビルドできないかとか少し調べたのですが、面倒なのでやめました(面倒とは!?)</p> <p>あとベアメタルな環境でRustを書きたかったんです、はい。</p> <p>幸い、ファームウエアの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>も回路図も<a href="https://github.com/Yowkees/keyball">公開されています</a>。なんとかなりそうですね。(keyballの作者であるYowkeesさん、ありがとうございます!)</p> <p>きっとRP2040のサンプルコードはインターネットにたくさん転がっているでしょうし、まずはそれを試してから、Rustでどう書くか考えることにしましょう。</p> <h3>まずは Hello, world だよね</h3> <p>そもそも、プログラムの書き込み方からわからない<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%A4%A5%B3%A5%F3">マイコン</a>を相手にファームウエアを書き始めるのは無謀というものですから、まずは入門からやっていきましょう。</p> <p>幸い、ネットの海を調べたところ、RaspberryPi公式でサンプルプログラムが公開されていました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fraspberrypi%2Fpico-examples" title="GitHub - raspberrypi/pico-examples" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/raspberrypi/pico-examples">github.com</a></cite></p> <p>しかも、いくつかのプログラムはprebuiltのバイナリまで提供されています。便利!(上記リンク中のテーブルの Link to prebuilt UF2 というカラムから飛べます。)</p> <p>とりあえずhello_usbのプログラムを書き込んでみましょう。</p> <p>…え、どうやって書き込むの?</p> <h3>BOOTSEL mode, picotool</h3> <p>とりあえずネットの海を探ると、picotoolという<a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>ツールが見つかり、ボードをBOOTSELモードというのに持っていくと、picotoolを使ってプログラムを書き込める(もしくはストレージが<a class="keyword" href="http://d.hatena.ne.jp/keyword/USB%A5%E1%A5%E2%A5%EA">USBメモリ</a>のように認識されるので、そこにファイルをコピーする方法も可)ということがわかりました。</p> <p>BOOTSELモードの入り方は、ボードの提供元であるSparkfunのページに画像付きで書かれています。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearn.sparkfun.com%2Ftutorials%2Fpro-micro-rp2040-hookup-guide%2Fall%23uf2-bootloader" title="Pro Micro RP2040 Hookup Guide - learn.sparkfun.com" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://learn.sparkfun.com/tutorials/pro-micro-rp2040-hookup-guide/all#uf2-bootloader">learn.sparkfun.com</a></cite></p> <p>基本的に、ボード上にある2つのボタンはRESETボタンとBOOTSELボタンになっているので、BOOTSELを押しながらRESETを押せばBOOTSELモードでボードが起動してプログラムが書き込めます。</p> <p>というわけで、いずれかの方法でhello_usbのバイナリ(<code>hello_world.uf2</code>)を書き込むと、なんとPro MicroがUSB modemとして振る舞い始めます。</p> <pre class="code" data-lang="" data-unlink>$ ls /dev/tty.usb* /dev/tty.usbmodem0000000000001</pre> <p>これの出力をscreenコマンドで見てみると、</p> <pre class="code" data-lang="" data-unlink>$ screen /dev/tty.usbmodem0000000000001 Hello, world! Hello, world! Hello, world! ...</pre> <p>OK, RP2040の世界にこんにちはできました。</p> <h3>でもね、そのボタン、押せないの…</h3> <p>さて、じゃあこの調子でファームウエアを書いていきましょう…と言いたいところなのですが、一つ困ったことがわかりました。</p> <p>この画像を見てください。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%D5%C5%BE%BA%DB%C8%BD">逆転裁判</a>で証拠品を提示するときの効果音)</p> <p><figure class="figure-image figure-image-fotolife" title="Pro Microの裏表に注目…(ボタンが押せない!)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230153257.jpg" alt="f:id:hikalium:20211230153257j:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>Pro Microの裏表に注目…(ボタンが押せない!)</figcaption></figure></p> <p>「この写真には、制作途中のKeyball46にPro Microが挿さっている様子が写っています。」</p> <p>「いたって普通のプリント基板とPro Microですね。何か問題でも?」</p> <p>「Pro Microの部分を見てください。何かに気づきませんか?」</p> <p>「いえ、いたって普通のPro Microだと思いますけど。先ほどあなたがおっしゃっていた通り、RP2040版であるという点は異常ですが、それはファームウエアを書くという話で決着がついたはずですよね。さっさとファームウエアを書き始めたらどうなんですか?」</p> <p>「ええ、私もそうしたいところです。ファームウエアが書き込めれば、の話ですが。」</p> <p>「そんなのボタンを押せばいいってさっき…ああああああっ!!!」</p> <p>「そう、ないんですよ。ボタンがね。」</p> <p>…おわかりいただけただろうか?なんとこの基板、Pro Microを裏面に装着するように設計されているため、ボタンが押せないのです。</p> <p>AVR版のPro Microだと、電源投入時にリセットボタンを長押しや連打することで書き込みモードに移行できるため、リセットボタンはタクトスイッチで基板上から操作できるように設計されているのですが、RP2040版の場合は、リセットボタンだけではなくBOOTSELボタンを押す必要があるのです。しかし、それは押すことができない!</p> <h3>ラズパイでラズパイにプログラムを書き込む - SWDって便利だな</h3> <p>ソフトウエア開発において、開発と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>の繰り返しを迅速に行うことは、開発効率の面からも非常に重要です。 最悪、Pro Microを毎回外して書き込み、そして基板上に戻す、ということも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B9%A5%EB">コンスル</a>ーピンのおかげでできなくはないでしょうが、非常に面倒ですし、そもそもそう何度も抜き差ししていたら<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%DC%BF%A8">接触</a>不良の原因になるでしょう。なにしろやる気がダダ落ちです。</p> <p>では、どうするか…上の画像を見ると、Pro Microの下側、qwiicと書いてあるところの上に、DとCと書かれたランドが露出しているのが見えます。</p> <p>これは一体なんでしょうか?</p> <blockquote><p>SWD Pins For advanced users, there are two pins (i.e. D for data/SWDIO and C for clock/SWCLK) on the back broken out for SWD programming on the back of the board. You'll need to solder <a class="keyword" href="http://d.hatena.ne.jp/keyword/wire">wire</a> to connect to these pins.</p></blockquote> <p><a href="https://learn.sparkfun.com/tutorials/pro-micro-rp2040-hookup-guide/all#hardware-overview">Pro Micro RP2040 Hookup Guide - learn.sparkfun.com</a></p> <p>ええ、私たちはAdvanced usersなので、これを使いましょう(満面の笑顔)。</p> <p><a href="https://developer.arm.com/architectures/cpu-architecture/debug-visibility-and-trace/coresight-architecture/serial-wire-debug">CoreSight Architecture | Serial Wire Debug &ndash; Arm Developer</a></p> <p>ARM社のドキュメントによれば、SWD(Serial <a class="keyword" href="http://d.hatena.ne.jp/keyword/Wire">Wire</a> Debug)を利用すると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>と同じようなことができる、と書いてあります。</p> <p>まあ簡潔にいえば、これをよしなにopenocd経由で操作してあげれば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>読み書きし放題、メモリ書き換え放題、要するになんでもやりたい放題できるということです。</p> <p>まあファームウエアを開発するんだから、これくらいやってもよいでしょう。</p> <p>まずはさくっとジャンパワイヤをSWDのランドにはんだ付けして、</p> <p><figure class="figure-image figure-image-fotolife" title="SWD の D, C および GND にジャンパワイヤを接続したようす"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230171833.png" alt="f:id:hikalium:20211230171833p:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>SWD の D, C および GND にジャンパワイヤを接続したようす</figcaption></figure></p> <p>もう一台どこのご家庭にも転がっている<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>を持ってきて、DをGPIO24, CをGPIO25に繋ぎます。(このピン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B5%A5%A4">アサイ</a>ンは、<a href="https://github.com/raspberrypi/openocd/blob/rp2040/tcl/interface/raspberrypi-swd.cfg">openocdに付属しているconfigファイル</a>に定義されています。)</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fforums.raspberrypi.com%2Fviewtopic.php%3Ft%3D302144" title="Poor Man&#39;s Pico No-Button-Boot (NBB) - Raspberry Pi Forums" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://forums.raspberrypi.com/viewtopic.php?t=302144">forums.raspberrypi.com</a></cite></p> <p>あとは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>上で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>のフォーラムに書いてあったいい感じのopenocdの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>を参考に適当にopenocdさんを呼び出すと</p> <pre class="code" data-lang="" data-unlink>openocd -f interface/raspberrypi-swd.cfg -f target/rp2040.cfg -c &#39;&#34;targets rp2040.core0; program ${PATH_TO_ELF} verify reset exit&#34;</pre> <p><code>${PATH_TO_ELF}</code>に指定したプログラムが書き込まれてターゲットが再起動します。これは便利!(書き込まれたバイナリはちゃんと永続化されているので、次回以降の起動時もこれが使われます。)(先ほど紹介したprebuiltのUF2ファイルはこの方法では読めないので、サンプルを手元でビルドして、UF2に変換される前のELFファイルを指定してあげてください。)</p> <p>よし、これでPro MicroをKeyball46の基板に挿しっぱなしでも大丈夫になりました。やっとファームウエアを書くステップに行けますね!</p> <h3>RustでRP2040をターゲットにしたプログラムを書く</h3> <p>先程紹介した <a href="https://github.com/raspberrypi/pico-examples">raspberrypi/pico-examples</a> は、残念ながら<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>で書かれています。</p> <p>せっかく書くなら、もっと現代的な言語で書きたいですよね?ということで調べてみると、RP2040向けのHALを提供してくれるcrateが見つかりました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Frp-rs%2Frp-hal" title="GitHub - rp-rs/rp-hal: A Rust Embedded-HAL for the rp series microcontrollers" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/rp-rs/rp-hal">github.com</a></cite></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EB%A5%B9%A5%AF%A5%E9%A5%C3%A5%C1">フルスクラッチ</a>で書くのも面白そうですが、動くとわかってからでも遅くはないので、ひとまずはこれを使うことにしましょう。</p> <p>先ほどと同様に、まずはサンプルを試してみます。</p> <p><a href="https://github.com/rp-rs/rp-hal/blob/main/boards/sparkfun-pro-micro-rp2040/examples/sparkfun_pro_micro_rainbow.rs">boards/sparkfun-pro-micro-rp2040/examples/sparkfun_pro_micro_rainbow.rs</a> に、Pro Micro (RP2040) 用のサンプルがあるので、これを<a href="https://github.com/rp-rs/rp-hal/tree/main/boards/sparkfun-pro-micro-rp2040">README.md</a>に書いてある通りにビルドします。</p> <pre class="code" data-lang="" data-unlink>cargo build --release --example sparkfun_pro_micro_rainbow</pre> <p>そうすると、<code>target/thumbv6m-none-eabi/release/examples/pro_micro_rainbow</code>にELFファイルが生成されるので、これを先程の方法で書き込んでみます。すると、LEDが虹色に光り始めます。やったね!(下の画像で緑色のLEDがそれです。)</p> <p><figure class="figure-image figure-image-fotolife" title="RustでRP2040のLチカ!"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230180209.png" alt="f:id:hikalium:20211230180209p:plain" width="1200" height="900" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>RustでRP2040のLチカ!</figcaption></figure></p> <h3>USB HID として振る舞いたい</h3> <p>さて、私たちはもう終わったクリスマスの電飾を作りたかったわけではなくて、キーボードとマウスとして振る舞う何かを作りたかったのでした。</p> <p>これを達成するためには、Pro Microさんに USB HID として振る舞ってもらう必要があるのですが、それをゼロからちょっと実装するのは大変です。</p> <p>そこで、rp-rs/rp-hal内の他のboard向けのサンプルを眺めてみたところ、<a href="https://github.com/rp-rs/rp-hal/blob/main/boards/rp-pico/examples/pico_usb_twitchy_mouse.rs">boards/rp-pico/examples/pico_usb_twitchy_mouse.rs</a> という、まさにこれがほしかった!みたいなサンプルが見つかりました。なので、これをさくっとsparkfun_pro_micro向けに移植してあげればOKです。</p> <p>実はpico向けにビルドしたバイナリを書き込むと普通に動いてしまうんですが(まあ同じSoCを使ってるからそれはそう)、せっかくHALがボードごとにあるので、ちょっと手直ししてあげるといいと思います。(適当にやった。)</p> <p>はい、これで「PCに繋ぐとマウスが小刻みに上下するので画面ロックを回避できる<del>邪悪</del>デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>」ができあがりました。意外と簡単だ!</p> <h3>キーボード機能を追加する</h3> <p>ではこの調子で<del>BadUSB</del>キーボード入力もできるようにしましょう。まずは、さっきのサンプルの実装を読んでみます。</p> <pre class="code" data-lang="" data-unlink> // Create a USB device with a fake VID and PID let usb_dev = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x16c0, 0x27da)) .manufacturer(&#34;Fake company&#34;) .product(&#34;Twitchy Mousey&#34;) .serial_number(&#34;TEST&#34;) .device_class(0xEF) // misc .build(); unsafe { // Note (safety): This is safe as interrupts haven&#39;t been started yet USB_DEVICE = Some(usb_dev); }</pre> <p>ここでデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>を作って、</p> <pre class="code" data-lang="" data-unlink> // Move the cursor up and down every 200ms loop { delay.delay_ms(100); let rep_up = MouseReport { x: 0, y: 4, buttons: 0, wheel: 0, pan: 0, }; push_mouse_movement(rep_up).ok().unwrap_or(0); delay.delay_ms(100); let rep_down = MouseReport { x: 0, y: -4, buttons: 0, wheel: 0, pan: 0, }; push_mouse_movement(rep_down).ok().unwrap_or(0); }</pre> <p>あとはここでマウスの動きをpushしているようです。push_mouse_movementの実装は、以下のような感じです。</p> <pre class="code" data-lang="" data-unlink>fn push_mouse_movement(report: MouseReport) -&gt; Result&lt;usize, usb_device::UsbError&gt; { cortex_m::interrupt::free(|_| unsafe { // Now interrupts are disabled, grab the global variable and, if // available, send it a HID report USB_HID.as_mut().map(|hid| hid.push_input(&amp;report)) }) .unwrap() }</pre> <p>ここで、自作OSでUSB HIDドライバを実装していた際の知識が役に立ってきます。</p> <p>まず、USB HID では、マウスの移動やキーボードの押し下げなどの情報は、レポートというデータとしてデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>から送られてきます。</p> <p>そして、ここが重要なのですが、USBは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>的に、常にホスト側<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>かデータの転送を開始できない仕組みになっています。これはどういうことかというと、USB<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>のレイヤでは、割り込みという概念が存在せず、ポーリングしかできない、ということです。</p> <p>ですが、キーボードやマウスが動くのは(CPUさんの時間軸から見たら)稀なので、ポーリングをするのは非効率的な気がしますよね?そこで、USBでは、USBコントローラがUSBデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>に対して定期的にデータ転送を要求して(ポーリング)、データがあればUSBコントローラからCPUに割り込みを発生させる、という仕組みになっています。</p> <p>というわけで、上のpush_mouse_movementが呼ばれても、実際にはまだホスト側にはその情報は伝わりません。その代わり、USBコントローラーが定期的に読んでくるとデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>側で割り込みが発生するので、そのタイミングでデータを送りつけてあげることになります。</p> <pre class="code" data-lang="" data-unlink>#[allow(non_snake_case)] #[interrupt] unsafe fn USBCTRL_IRQ() { // Handle USB request let usb_dev = USB_DEVICE.as_mut().unwrap(); let usb_hid = USB_HID.as_mut().unwrap(); usb_dev.poll(&amp;mut [usb_hid]); }</pre> <p>これが、その「デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>側の割り込みハンドラ」です。これが呼ばれるタイミングで、デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>からホストへとデータ転送が走ることになります。</p> <p>この割り込みの周期については、もっと上の方で</p> <pre class="code" data-lang="" data-unlink> let usb_hid = HIDClass::new(bus_ref, MouseReport::desc(), 60);</pre> <p>とすることで、HIDClassを初期化する際に、60msに設定されています。詳細は、<a href="https://docs.rs/usbd-hid/latest/usbd_hid/hid_class/struct.HIDClass.html">docs.rsにあるドキュメント</a>を読むとわかりやすいと思います。</p> <p>ここまでが、大まかなサンプルのデータの流れです。</p> <p>では、これを改造して、キーボードの情報も送るにはどうすればよいでしょうか?</p> <p><a href="https://docs.rs/usbd-hid/latest/usbd_hid/index.html">usbd-hid</a>のドキュメントをさらに読むと、MouseReportの隣に<a href="https://docs.rs/usbd-hid/latest/usbd_hid/descriptor/struct.KeyboardReport.html">KeyboardReport</a>があることがわかります。これを使えばなんとかいけそうですね。</p> <p>見よう見まねで、こんな感じにしてみます。(振り返って書いているので雰囲気だけ掴んでください。)</p> <pre class="code" data-lang="" data-unlink>static mut USB_HID_KEYBOARD: Option&lt;HIDClass&lt;hal::usb::UsbBus&gt;&gt; = None; fn main() -&gt; ! { ... let usb_hid_keyboard = HIDClass::new(bus_ref, KeyboardReport::desc(), 10); unsafe { USB_HID_KEYBOARD = Some(usb_hid_keyboard); } ... loop { ... let rep = KeyboardReport { modifier: 0, reserved: 0, leds: 0, keycodes: [0x04 /* A */, 0, 0, 0, 0, 0], }; push_key_event(rep).ok().unwrap_or(0); ... } .... } pub fn push_key_event(report: KeyboardReport) -&gt; Result&lt;usize, usb_device::UsbError&gt; { cortex_m::interrupt::free(|_| unsafe { USB_HID_KEYBOARD.as_mut().map(|hid| hid.push_input(&amp;report)) }) .unwrap() } ... #[allow(non_snake_case)] #[interrupt] unsafe fn USBCTRL_IRQ() { // Handle USB request let usb_dev = USB_DEVICE.as_mut().unwrap(); let usb_hid_mouse = USB_HID.as_mut().unwrap(); let usb_hid_keyboard = USB_HID_KEYBOARD.as_mut().unwrap(); // new usb_dev.poll(&amp;mut [usb_hid_mouse, usb_hid_keyboard /* new */]); } ...</pre> <p>KeyboardReportのkeycodesについては、<a href="https://usb.org/sites/default/files/hut1_22.pdf">HID Usage Tables FOR Universal Serial Bus (USB)</a>の<code>10: Keyboard/Keypad Page (0x07)</code> に定義があります。また、ここに<a href="https://www.win.tue.nl/~aeb/linux/kbd/scancodes-14.html">pdfよりも軽い表</a>があります。</p> <p>これで、マウスの上下移動とともに、<code>a</code>が入力され続けるはずです。</p> <p>実際、動きました。…<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>では。</p> <p>しかし、なぜか<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>ではマウスもキーボードも動かなくなってしまいました。一体なぜでしょうか?</p> <h3>Boot keyboard のフォーマットに切り替える</h3> <p><a href="https://wiki.osdev.org/USB_Human_Interface_Devices">osdev.orgの記事</a>によれば、USBキーボードのReportの形式は、</p> <pre class="code" data-lang="" data-unlink>pub struct KeyboardReport2 { pub modifier: u8, pub reserved: u8, pub keycodes: [u8; 6], }</pre> <p>のような形式になっているようです。…あれっ、先ほど利用したusbd-hidのKeyboardReportには存在する、ledsのフィールドがないですね…。</p> <p>これは完全に想像ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>ではUSBキーボードのレポート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%AF%A5%EA%A5%D7%A5%BF">ディスクリプタ</a>をきちんと解釈せず、Boot protocolに沿っていると仮定しているのではないでしょうか。</p> <p>レポート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%AF%A5%EA%A5%D7%A5%BF">ディスクリプタ</a>というのは、Reportがどのような形式になっているのかをUSBデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>がUSBホスト側に伝えるためのデータで、</p> <pre class="code" data-lang="" data-unlink> let usb_hid_keyboard = HIDClass::new(bus_ref, KeyboardReport::desc(), 10);</pre> <p>この行の <code>KeyboardReport::desc()</code>がそれにあたります。このdescは、<a href="https://docs.rs/usbd-hid/latest/src/usbd_hid/descriptor.rs.html#59">ソース</a>を確認すると</p> <pre class="code" data-lang="" data-unlink>#[gen_hid_descriptor( (collection = APPLICATION, usage_page = GENERIC_DESKTOP, usage = KEYBOARD) = { (usage_page = KEYBOARD, usage_min = 0xE0, usage_max = 0xE7) = { #[packed_bits 8] #[item_settings data,variable,absolute] modifier=input; }; (usage_min = 0x00, usage_max = 0xFF) = { #[item_settings constant,variable,absolute] reserved=input; }; (usage_page = LEDS, usage_min = 0x01, usage_max = 0x05) = { #[packed_bits 5] #[item_settings data,variable,absolute] leds=output; }; (usage_page = KEYBOARD, usage_min = 0x00, usage_max = 0xDD) = { #[item_settings data,array,absolute] keycodes=input; }; } )]</pre> <p>このようなマクロによって生成されています。</p> <p>おそらく、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>はこれを解釈して正しくReportを読み取れるのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>は期待しているデータ構造と送られてきたReportが一致しないため、そこであきらめてしまっているのではないかと考えられます。</p> <p>というわけで、osdev.orgやUSBのドキュメントに記載されている、Boot protocolの形式のほうを利用することにしましょう。これで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>でも<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>でも動きます!</p> <h3>その他のハマりポイント</h3> <p>勢いで書いていたらめっちゃ記事が長くなってきたので、残りはさくっといきます。もし詳しく知りたい方がいらっしゃったら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>などで<a href="https://twitter.com/hikalium">hikalium</a>宛にリプライを飛ばすか、<a href="https://www.youtube.com/channel/UCMsstGhINXdpMqo9tsElCMQ">低レイヤーガール</a>チャンネルの配信の際にでもコメントで聞いてください。</p> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>基板がお返事してくれない…</h4> <h5>Pro Micro にピンをつけた際、はんだが流れて NCSとMOSIがショートしてた</h5> <p>状況: <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>制御基板さんにSPI通信でお話ししても0xFFしか返ってこない。ロジアナで見たらNCSとMOSIが仲良く同じ波形を出してた。</p> <p><figure class="figure-image figure-image-fotolife" title="上から順にNCS, CLK, MOSI, MISOの波形"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211230/20211230185805.png" alt="f:id:hikalium:20211230185805p:plain" width="1200" height="272" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>上から順にNCS, CLK, MOSI, MISOの波形</figcaption></figure></p> <p>解決策: 一回該当するピンのハンダを除去してやりなおし。</p> <h5>NCSが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%F3%A5%B6%A5%AF%A5%B7%A5%E7%A5%F3">トランザクション</a>が終わるよりも前にhighに戻っちゃう</h5> <p>状況: ショートを直してもまだお返事もらえない。波形を見てみると、NCSが一瞬しかlowになってなかった。</p> <p>原因: <a href="https://github.com/rp-rs/rp-hal/blob/release_030/rp2040-hal/src/spi.rs#L266">rp-rs/rp-halのSpi::write</a>は、データ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>に書き込むだけで、送信完了を待ってはくれないのであった。(涙)</p> <p>解決策:</p> <p>rp-halをforkして<a href="https://github.com/hikalium/rp-hal/commit/7597d2e33ba8c5a4fa00b0a4dadf34ac50aa88ae">Spi::deviceをとれるようにし</a>、それを直接使ってステータス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>を読み、sendが完了するのをloopで待つようにした。</p> <pre class="code" data-lang="" data-unlink> loop { let sspsr = spi.borrow_mut().device().sspsr.read(); if sspsr.tfe().bit_is_set() &amp;&amp; sspsr.bsy().bit_is_clear() { break; } delay.borrow_mut().delay_us(10); }</pre> <h1>まとめ</h1> <p>とりあえず動くようになった。</p> <p><figure class="figure-image figure-image-fotolife" title="完成した図。トラックボールもキーボードも動く!(SWDの線がまだ生えてるのはご愛嬌)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20211231/20211231145356.png" alt="f:id:hikalium:20211231145356p:plain" width="1200" height="511" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>完成した図。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>もキーボードも動く!(SWDの線がまだ生えてるのはご愛嬌)</figcaption></figure></p> <p>まだキーマップが練りきれていないのと、TRRSケーブルを介した接続には対応していないほか、私はこれまでErgo Dox EZを使っていたので、いかにこのキーの少なさで生きていくかなど課題は山積みですが、少しずつ実運用に投入していきたいと思います。(この記事の一部はこれで書きました。)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">さて、普通に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A5%E9%A5%C3%A5%AF%A5%DC%A1%BC%A5%EB">トラックボール</a>も動くようになりましたが…(あとは左手側を組み上げるだけ) <a href="https://t.co/BTYvj407YZ">pic.twitter.com/BTYvj407YZ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1476363770742345728?ref_src=twsrc%5Etfw">2021年12月30日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>自作キーボード、たのしい!みんなもやろう!!</p> <h1>謝辞</h1> <p>Keyball46を設計された<a href="https://twitter.com/Yowkees">Yowkees</a>さん、自作キーボードに必要なパーツを販売している<a href="https://shop.yushakobo.jp/">遊舎工房</a>さん、そして数年前の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Cookpad">Cookpad</a>自作キーボード<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%F3">インターン</a>(?)で自作キーボードの基礎を教えてくれた<a href="https://twitter.com/KOBA789">KOBA789</a>さん、ありがとうございました!</p> <h1>成果物</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhikalium%2Fkeyball-rs" title="GitHub - hikalium/keyball-rs" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/hikalium/keyball-rs">github.com</a></cite></p> hikalium Raspberry Pi 4をJTAGデバッグしてみる(FTDI C232HM-DDHSL-0使用) hatenablog://entry/26006613788053782 2021-07-18T21:40:13+09:00 2021-09-20T17:55:36+09:00 概要 主な登場人物 決戦結線の時 JTAG ⇔ C232HM-DDHSL-0 UART ⇔ TTL-232RG-VREG3V3-WE 接続イメージ ソフトウエアの設定 openocdをインストールする Raspberry Pi 側でJTAGインターフェイスを有効化する ついでにシリアルポート出力とかも有効化しておく 参考: 私のconfig.txtの末尾はこうなっている openocdの設定 インターフェイスの設定 ターゲットの設定 動かしてみる openocdとのやりとり gdbとあわせて使う 付録: openocdがうまくいかないとき JTAGアダプタとシリアルケーブルがつながったRasp… <ul class="table-of-contents"> <li><a href="#概要">概要</a></li> <li><a href="#主な登場人物">主な登場人物</a></li> <li><a href="#決戦結線の時">決戦結線の時</a><ul> <li><a href="#JTAG--C232HM-DDHSL-0">JTAG ⇔ C232HM-DDHSL-0</a></li> <li><a href="#UART--TTL-232RG-VREG3V3-WE">UART ⇔ TTL-232RG-VREG3V3-WE</a></li> <li><a href="#接続イメージ">接続イメージ</a></li> </ul> </li> <li><a href="#ソフトウエアの設定">ソフトウエアの設定</a><ul> <li><a href="#openocdをインストールする">openocdをインストールする</a></li> <li><a href="#Raspberry-Pi-側でJTAGインターフェイスを有効化する">Raspberry Pi 側でJTAGインターフェイスを有効化する</a></li> <li><a href="#ついでにシリアルポート出力とかも有効化しておく">ついでにシリアルポート出力とかも有効化しておく</a></li> <li><a href="#参考-私のconfigtxtの末尾はこうなっている">参考: 私のconfig.txtの末尾はこうなっている</a></li> </ul> </li> <li><a href="#openocdの設定">openocdの設定</a><ul> <li><a href="#インターフェイスの設定">インターフェイスの設定</a></li> <li><a href="#ターゲットの設定">ターゲットの設定</a></li> </ul> </li> <li><a href="#動かしてみる">動かしてみる</a><ul> <li><a href="#openocdとのやりとり">openocdとのやりとり</a></li> </ul> </li> <li><a href="#gdbとあわせて使う">gdbとあわせて使う</a></li> <li><a href="#付録-openocdがうまくいかないとき">付録: openocdがうまくいかないとき</a></li> </ul> <p><figure class="figure-image figure-image-fotolife" title="JTAGアダプタとシリアルケーブルがつながったRaspberry Pi 4"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20210718/20210718212859.jpg" alt="f:id:hikalium:20210718212859j:plain" width="1200" height="686" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタとシリ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B1%A1%BC">アルケー</a>ブルがつながった<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4</figcaption></figure></p> <h2 id="概要">概要</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>でベアメタルプログラミングをするときに、CPUが今実際にどこの命令を実行しているか、メモリ上にどのような値が存在するか…などの情報を確認できると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>が非常に楽になります。それを可能にしてくれるのが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>という<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>です。</p> <p>今回は、FTDI社製のケーブルを使用して、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4の<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>にアクセスしてみました。前半部分はケーブル固有の話もあるので、他の<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>ケーブルをお持ちの方は、それぞれのマニュアルを参照して適宜読み替えていただく必要があります。一方後半部分は、openocdを使って<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>経由で<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4の情報を取得する一般的な方法について説明しますので、みなさんの環境でも役立つかもしれません。参考にしていただければ幸いです。</p> <h2 id="主な登場人物">主な登場人物</h2> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4 Model B <ul> <li>BCM2711というSoCが載っています。</li> </ul> </li> <li>FTDI C232HM-DDHSL-0 <ul> <li>このケーブルはMPSSE(Multi-Protocol Synchronous Serial Engine) といって、モードを切り替えれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>以外にもSPIやI2Cといった通信もできるようです。</li> <li>C232HM-<strong>D</strong>DHSL-0とC232HM-<strong>E</strong>DHSL-0の違いは、通信に使う電圧レベルです(3.3Vと5.0V)。<a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/gpio/README.md">Raspberry PiのGPIOは3.3V</a>なので、間違えないようにしましょう。</li> </ul> </li> <li>FTDI <a class="keyword" href="http://d.hatena.ne.jp/keyword/TTL">TTL</a>-232RG-VREG3V3-WE <ul> <li>このケーブルは<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>通信には関係ないですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>のUART(シリアルポート)を読むために使っています。ベアメタルプログラミングするなら、基本的にシリアルは生命線になるので、シリアルを読めるケーブルは何らかのものを持っておくとよいと思います。</li> <li>例によって、これも電圧レベルによって似た品番のものがあるので、他の変換ケーブルやボードを使う際も、3.3Vのものを買うようにしましょう。</li> <li>ちなみにこのケーブルは末端が電線剥き出しでコネクタがついてないので、私はそれをブレッドボードに刺してそこからRasPiに延ばしています。コネクタがついているタイプのものも他の製品だとあるようなので、そっちを買った方が便利かもしれません。</li> </ul> </li> </ul> <h2 id="決戦結線の時"> <del>決戦</del>結線の時</h2> <p>というわけで早速ケーブルとRasPiをつないでゆきます。RasPiの電源を落としてから作業しましょう。</p> <p>落とし穴としては、RasPiのGPIOピンの番号と、物理ピン番号(GPIOヘッダ上の位置)は異なる、というところです。</p> <p>詳しくは<a href="https://www.raspberrypi.org/documentation/usage/gpio/">Raspberry Pi 公式のドキュメント</a>に解説があるので、それをチェックしてください。</p> <p>(以下はあくまでも参考として、鵜呑みにせずに自分で本当に合っているかチェックしながら接続してください!)</p> <h3 id="JTAG--C232HM-DDHSL-0"><a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a> ⇔ C232HM-DDHSL-0</h3> <p><a href="https://ftdichip.com/wp-content/uploads/2020/07/DS_C232HM_MPSSE_CABLE.pdf">ケーブル自体のデータシート</a>も参考にしてください。</p> <table> <thead> <tr> <th> ケーブルの色 </th> <th> GPIOピン番号 </th> <th> 物理ピン番号 </th> <th> GPIOヘッダを右上においたときの場所</th> </tr> </thead> <tbody> <tr> <td>Brown (TMS)</td> <td>27 (ARM_TMS)</td> <td>13</td> <td>上から7番目の左</td> </tr> <tr> <td>Grey (TRST)</td> <td>22 (ARM_TRST)</td> <td>15</td> <td>上から8番目の左</td> </tr> <tr> <td>Blue (RTCK)</td> <td>23 (ARM_RTCK)</td> <td>16</td> <td>上から8番目の右</td> </tr> <tr> <td>Green (TDO)</td> <td>24 (ARM_TDO)</td> <td>18</td> <td>上から9番目の右</td> </tr> <tr> <td>Orange (<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCK">TCK</a>)</td> <td>25 (ARM_<a class="keyword" href="http://d.hatena.ne.jp/keyword/TCK">TCK</a>)</td> <td>22</td> <td>上から11番目の右</td> </tr> <tr> <td>Yellow (TDI)</td> <td>26 (ARM_TDI)</td> <td>37</td> <td>上から19番目の左=下から2番目の左</td> </tr> <tr> <td>Black (GND)</td> <td>GND</td> <td>39, etc...</td> <td>一番左下など</td> </tr> </tbody> </table> <p>RTCKを使わない記事もインターネット上にはありましたが、これをつなぐと通信が格段に安定したのでこのようにしています。</p> <h3 id="UART--TTL-232RG-VREG3V3-WE">UART ⇔ <a class="keyword" href="http://d.hatena.ne.jp/keyword/TTL">TTL</a>-232RG-VREG3V3-WE</h3> <p><a href="https://ftdichip.com/wp-content/uploads/2020/07/DS_TTL-232RG_CABLES.pdf">ケーブル自体のデータシート</a>も参考にしてください。</p> <table> <thead> <tr> <th> ケーブルの色 </th> <th> GPIOピン番号 </th> <th> 物理ピン番号 </th> <th> GPIOヘッダを右上においたときの場所</th> </tr> </thead> <tbody> <tr> <td>Yellow(RXD)</td> <td>14</td> <td>8</td> <td>上から4番目の右</td> </tr> <tr> <td>Black(GND)</td> <td>GND</td> <td>9, etc...</td> <td>上から5番目の左など</td> </tr> <tr> <td>Orange(TXD)</td> <td>15</td> <td>10</td> <td>上から5番目の右</td> </tr> </tbody> </table> <h3 id="接続イメージ">接続イメージ</h3> <p>全部つないでみたときの参考写真を貼っておきました。(写真の向きは、GPIOヘッダを左上にみたときの例なので、上の説明と対応させる場合は、90度首を傾けてみてください。)</p> <p>シリアル変換ケーブルから伸びている線は、写真上側のブレッドボードでジャンパワイヤに変換されてきているので、上の説明に書かれている色と、写真中の線の色は一致しません。</p> <p>画面左側、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタから伸びている線の色は、上に書いてある説明と一致します。</p> <p><figure class="figure-image figure-image-fotolife" title="JTAGアダプタとシリアル出力の接続例"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20210718/20210718213206.jpg" alt="f:id:hikalium:20210718213206j:plain" width="1200" height="758" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタとシリアル出力の接続例</figcaption></figure></p> <h2 id="ソフトウエアの設定">ソフトウエアの設定</h2> <p>今回の環境は <a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a> 11.4ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>などの他の環境でも、似たような設定をすれば動作するはずです。</p> <h3 id="openocdをインストールする">openocdをインストールする</h3> <p>最新のopenocdを<a href="https://brew.sh/">Homebrew</a>経由でインストールします。</p> <pre class="code" data-lang="" data-unlink>brew install openocd --HEAD</pre> <p>私の環境では、以下のようなエラーメッセージが出ました。</p> <pre class="code" data-lang="" data-unlink>$ brew install openocd --HEAD ... ==&gt; Installing open-ocd --HEAD ==&gt; ./bootstrap nosubmodule ==&gt; ./configure --prefix=/usr/local/Cellar/open-ocd/HEAD-cff0e41 --enable-buspir ==&gt; make install Error: An unexpected error occurred during the `brew link` step The formula built, but is not symlinked into /usr/local Cannot link open-ocd Another version is already linked: /usr/local/Cellar/open-ocd/0.10.0 Error: Cannot link open-ocd Another version is already linked: /usr/local/Cellar/open-ocd/0.10.0</pre> <p>このエラーは、すでに他のバージョンのopenocdがインストールされている場合に表示されます。この場合、インストールした最新のopenocdにはPATHが通っていない状態になっていますので、パスを直接指定して実行してあげる必要があります。(もちろん、強制的にPATHを通す(link)することも可能ですが、各自の判断にお任せします。)</p> <p>私の環境では、<code>/usr/local/Cellar/open-ocd/HEAD-cff0e41/bin/openocd</code>にインストールされていましたので、これを直接実行できることを確認します。</p> <pre class="code" data-lang="" data-unlink>$ /usr/local/Cellar/open-ocd/HEAD-cff0e41/bin/openocd --version Open On-Chip Debugger 0.11.0+dev-00236-gcff0e417d-dirty (2021-06-28-20:42) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html</pre> <p>バージョン情報が正しく表示されればOKです。</p> <h3 id="Raspberry-Pi-側でJTAGインターフェイスを有効化する"><a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 側で<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>を有効化する</h3> <p>デフォルトでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>は無効になっており、該当するピンは通常のGPIOポートとして機能するように設定されています。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>を有効化するには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>のSDカード内にある config.txtというファイルの[all]セクションの配下に、以下のような記述を追加します。</p> <pre class="code" data-lang="" data-unlink>enable_jtag_gpio=1</pre> <p>これにより、起動時に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a>のファームウエアがこの設定ファイルを読み込んだ際に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>を有効化してくれます。</p> <p>詳しくは、公式のドキュメントを参照してください。</p> <ul> <li><a href="https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md">Raspberry Pi Documentation - Configuration</a></li> <li><a href="https://www.raspberrypi.org/documentation/configuration/config-txt/conditional.md">Raspberry Pi Documentation - Configuration</a></li> </ul> <h3 id="ついでにシリアルポート出力とかも有効化しておく">ついでにシリアルポート出力とかも有効化しておく</h3> <pre class="code" data-lang="" data-unlink>enable_uart=1</pre> <h3 id="参考-私のconfigtxtの末尾はこうなっている">参考: 私のconfig.txtの末尾はこうなっている</h3> <p>他にもいろいろ設定を入れてこんな感じになっています。参考までに。(この記事で解説したことを試すには、上で説明した2つを設定するだけで大丈夫なはずです。)</p> <pre class="code" data-lang="" data-unlink>... [all] #dtoverlay=vc4-fkms-v3d arm_64bit=1 init_uart_clock=48000000 init_uart_baud=115200 enable_uart=1 enable_jtag_gpio=1</pre> <h2 id="openocdの設定">openocdの設定</h2> <p>それでは早速openocdを使っていきたいのですが、使うためにはいくつか設定ファイルを作成する必要があります。</p> <h3 id="インターフェイスの設定"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>の設定</h3> <p>まず、以下のような内容のファイルを作成し<code>c232hm-edhsl-0.cfg</code>という名前で保存します。</p> <pre class="code" data-lang="" data-unlink>adapter driver ftdi ftdi_vid_pid 0x0403 0x6014 ftdi_device_desc C232HM-DDHSL-0 # ftdi_layout_init &lt;values&gt; &lt;directions&gt; # initial value: # 0078 = 0000 0000 0001 1000 # TRST, TMS=1, all others zero # initial direction: # 0111 = GPIOL3=RTCK=input, GPIOL2=dontcare=output, GPOL1=SRST=output, GPIOL0=TRST=output # 1011 = [1=TMS=output, 0=TDO=input, 1=TDI=output, 1=TCK=output] ftdi_layout_init 0x0018 0x007b # GPIOL0 is TRST ftdi_layout_signal nTRST -data 0x0010</pre> <p>(参考にした<a href="https://metebalci.com/blog/bare-metal-raspberry-pi-3b-jtag/">ブログ記事</a> のものに比べると、最新のopenocdに合わせて少し修正してあります。)</p> <p>このファイルには、使用する<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタ(今回の場合はFTDI C232HM-DDHSL-0)に固有の設定が記載されています。そのため、別の<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタを使用する際は、それに合ったファイルを作成する必要があります。場合によっては標準で提供されていることもあるので、他のアダプタをお使いの方は各自で調べてみてください。</p> <h3 id="ターゲットの設定">ターゲットの設定</h3> <p>次に、以下のような内容のファイルを作成し<code>raspi4.cfg</code>という名前で保存します。</p> <pre class="code" data-lang="" data-unlink>set _CHIPNAME bcm2711 set _DAP_TAPID 0x4ba00477 adapter speed 1000 transport select jtag reset_config trst_and_srst telnet_port 4444 # create tap jtag newtap auto0 tap -irlen 4 -expected-id $_DAP_TAPID # create dap dap create auto0.dap -chain-position auto0.tap set CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000} set DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000} set _cores 4 set _TARGETNAME $_CHIPNAME.a72 set _CTINAME $_CHIPNAME.cti set _smp_command &#34;&#34; for {set _core 0} {$_core &lt; $_cores} { incr _core} { cti create $_CTINAME.$_core -dap auto0.dap -ap-num 0 -baseaddr [lindex $CTIBASE $_core] set _command &#34;target create ${_TARGETNAME}.$_core aarch64 \ -dap auto0.dap -dbgbase [lindex $DBGBASE $_core] \ -coreid $_core -cti $_CTINAME.$_core&#34; if {$_core != 0} { set _smp_command &#34;$_smp_command $_TARGETNAME.$_core&#34; } else { set _smp_command &#34;target smp $_TARGETNAME.$_core&#34; } eval $_command } eval $_smp_command targets $_TARGETNAME.0</pre> <p>(こちらも、<a href="https://qiita.com/tnishinaga/items/89af35b32b6c4698cf9f">参考にした記事</a>をベースに、最新のopenocdに合わせて少し修正を加えたものになります。)</p> <p>このファイルには、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>対象のデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>(今回の場合は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4 / BCM2711)に固有の設定が記載されています。そのため、もし異なるボードを<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>したい場合には、それぞれに合ったファイルを作成して使用する必要があります。</p> <h2 id="動かしてみる">動かしてみる</h2> <p>では、編集済みのconfig.txtが入った<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> OS入りのSDカードを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4に挿入し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>ケーブルやシリアル変換ケーブルをPCにさして、最後に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> 4に電源をさして起動してみましょう。その後、以下のコマンドを実行してみてください。</p> <pre class="code" data-lang="" data-unlink>/usr/local/Cellar/open-ocd/HEAD-cff0e41/bin/openocd -f c232hm-edhsl-0.cfg -f raspi4.cfg</pre> <p>(最初のopenocdへのパスは、適宜環境に合わせて読みかえてください。)</p> <p>すべてが正しく動作していれば、以下のような出力が得られ、サーバーが待受状態になります。</p> <pre class="code" data-lang="" data-unlink>$ /usr/local/Cellar/open-ocd/HEAD-cff0e41/bin/openocd -f c232hm-edhsl-0.cfg -f raspi4.cfg Open On-Chip Debugger 0.11.0+dev-00236-gcff0e417d-dirty (2021-06-28-20:42) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : clock speed 1000 kHz Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4) Info : bcm2711.a72.0: hardware has 6 breakpoints, 4 watchpoints Info : bcm2711.a72.1: hardware has 6 breakpoints, 4 watchpoints Info : bcm2711.a72.2: hardware has 6 breakpoints, 4 watchpoints Info : bcm2711.a72.3: hardware has 6 breakpoints, 4 watchpoints Info : starting gdb server for bcm2711.a72.0 on 3333 Info : Listening on port 3333 for gdb connections</pre> <h3 id="openocdとのやりとり">openocdとのやりとり</h3> <p>参考:</p> <ul> <li><a href="https://metebalci.com/blog/bare-metal-raspberry-pi-3b-jtag/">https://metebalci.com/blog/bare-metal-raspberry-pi-3b-jtag/</a></li> <li><a href="http://openocd.org/doc/html/General-Commands.html">General Commands (OpenOCD User&rsquo;s Guide)</a></li> </ul> <p>上の出力に書かれている通り、<a class="keyword" href="http://d.hatena.ne.jp/keyword/telnet">telnet</a>などで4444番ポートにアクセスすると、openocdとおはなしできます。</p> <pre class="code" data-lang="" data-unlink>$ telnet localhost 4444 Trying ::1... telnet: connect to address ::1: Connection refused Trying 127.0.0.1... Connected to localhost. Escape character is &#39;^]&#39;. Open On-Chip Debugger &gt; </pre> <p>ここにコマンドを打つと、いろいろ見れます。</p> <p><code>targets</code>: 各ターゲット(今回の場合CPUコア)を一覧表示できる</p> <pre class="code" data-lang="" data-unlink>&gt; targets TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0* bcm2711.a72.0 aarch64 little auto0.tap running 1 bcm2711.a72.1 aarch64 little auto0.tap running 2 bcm2711.a72.2 aarch64 little auto0.tap running 3 bcm2711.a72.3 aarch64 little auto0.tap running</pre> <p><code>targets bcm2711.a72.1</code>のように、TargetNameを指定すれば、現在選択しているtargetを変更できる。</p> <p><code>halt</code>: 実行を停止させる。</p> <pre class="code" data-lang="" data-unlink>&gt; halt bcm2711.a72.1 cluster 0 core 1 multi core bcm2711.a72.2 cluster 0 core 2 multi core bcm2711.a72.2 halted in AArch64 state due to debug-request, current mode: EL2H cpsr: 0x000003c9 pc: 0x80 MMU: disabled, D-Cache: disabled, I-Cache: disabled bcm2711.a72.3 cluster 0 core 3 multi core bcm2711.a72.3 halted in AArch64 state due to debug-request, current mode: EL2H cpsr: 0x000003c9 pc: 0x80 MMU: disabled, D-Cache: disabled, I-Cache: disabled bcm2711.a72.0 cluster 0 core 0 multi core bcm2711.a72.0 halted in AArch64 state due to debug-request, current mode: EL2H cpsr: 0x600003c9 pc: 0x813d8 MMU: disabled, D-Cache: disabled, I-Cache: disabled bcm2711.a72.1 halted in AArch64 state due to debug-request, current mode: EL2H cpsr: 0x000003c9 pc: 0x80 MMU: disabled, D-Cache: disabled, I-Cache: disabled &gt; targets TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0 bcm2711.a72.0 aarch64 little auto0.tap halted 1* bcm2711.a72.1 aarch64 little auto0.tap halted 2 bcm2711.a72.2 aarch64 little auto0.tap halted 3 bcm2711.a72.3 aarch64 little auto0.tap halted</pre> <p><code>reg</code>: <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>を表示する</p> <pre class="code" data-lang="" data-unlink>&gt; reg ===== Aarch64 registers (0) x0 (/64): 0x000000000000006c (dirty) (1) x1 (/64): 0x00000000ffffffff (2) x2 (/64) ...</pre> <p><code>dirty</code>と書かれているデータは、openocdがキャッシュしているものなので、もし生の値を反映させたかったら、以下のようにすると強制的に読み書きできる。</p> <pre class="code" data-lang="" data-unlink>reg x0 force</pre> <p>キャッシュ情報とかも見れます</p> <pre class="code" data-lang="" data-unlink>&gt; aarch64 cache_info L1 I-Cache: linelen 64, associativity 3, nsets 256, cachesize 48 KBytes L1 D-Cache: linelen 64, associativity 2, nsets 256, cachesize 32 KBytes L2 D-Cache: linelen 64, associativity 16, nsets 1024, cachesize 1024 KBytes</pre> <p>メモリの読み書きもできちゃいます!たとえば0x80000(<a class="keyword" href="http://d.hatena.ne.jp/keyword/raspberry%20pi">raspberry pi</a> 4における<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>のロードアドレス)をみると</p> <pre class="code" data-lang="" data-unlink>&gt; mdw 0x80000 0x00080000: d53800a1</pre> <p>と書いてありますが、今回起動したイメージの先頭を確認してみると</p> <pre class="code" data-lang="" data-unlink>$ hexdump -C kernel8.img | head -n 1 00000000 a1 00 38 d5 21 04 40 92 42 01 00 58 3f 00 02 eb |..8.!.@.B..X?...|</pre> <p>たしかに一致していますね!</p> <h2 id="gdbとあわせて使う"><a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>とあわせて使う</h2> <p>参考: <a href="http://openocd.org/doc/html/GDB-and-OpenOCD.html">GDB and OpenOCD (OpenOCD User&rsquo;s Guide)</a></p> <p>openocdの起動時のメッセージを注意深く読むと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>のサーバーも待ち受けていることがわかります。</p> <pre class="code" data-lang="" data-unlink>Info : starting gdb server for bcm2711.a72.0 on 3333 Info : Listening on port 3333 for gdb connections</pre> <p>ということで、さっそくつないでみましょう。今回使った<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>のバージョンは以下の通り。</p> <pre class="code" data-lang="" data-unlink>$ gdb --version | head -n 1 GNU gdb (GDB) 9.2</pre> <p>まず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>を引数なしで起動します。</p> <pre class="code" data-lang="" data-unlink>gdb</pre> <p>そのあと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>のプロンプトに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>とターゲット情報を打ち込んで、リモート<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>をはじめます。</p> <p>私が試した例では、config.txtに<code>arm_64bit=1</code>と書いた状態でaarch64のバイナリを実行している状態なので、以下のようにaarch64をターゲットとして指定します。</p> <pre class="code" data-lang="" data-unlink>(gdb) set architecture aarch64 The target architecture is assumed to be aarch64 (gdb) target extended-remote localhost:3333 Remote debugging using localhost:3333 warning: No executable has been specified and target does not support determining executable automatically. Try using the &#34;file&#34; command. 0x00000000000813d8 in ?? ()</pre> <p>一方、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20Pi">Raspberry Pi</a> OSは記事執筆現在は32bit(armv7l)で動作しているので、もしそのようなターゲットを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>したい場合は、aarch64の代わりにarmv8-aにするとよいでしょう。</p> <pre class="code" data-lang="" data-unlink>set architecture armv8-a target extended-remote localhost:3333</pre> <p>もし間違ったarchを指定していたら、以下のようなエラーメッセージが出るので、そのときは別のarchを指定してやり直せばOKです。</p> <pre class="code" data-lang="" data-unlink>warning: Selected architecture armv8-a is not compatible with reported target architecture aarch64 warning: Architecture rejected target-supplied description</pre> <p>さて、これで<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>がつながったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>し放題です。いつものinfo registersとかもばっちり動きます。</p> <pre class="code" data-lang="" data-unlink>(gdb) info registers x0 0x0 0 x1 0x8192d 530733 x2 0x2 2 x3 0x80264 524900 ...</pre> <p>もちろん、今実行しているバイナリが手元にあれば、それを読み込んで<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>することもできます。</p> <pre class="code" data-lang="" data-unlink>$ file target/aarch64-unknown-none-softfloat/release/kernel target/aarch64-unknown-none-softfloat/release/kernel: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped $ gdb target/aarch64-unknown-none-softfloat/release/kernel GNU gdb (GDB) 9.2 ... (gdb) target extended-remote localhost:3333 Remote debugging using localhost:3333 0x00000000000813d8 in kernel::kernel_main () (gdb) disas Dump of assembler code for function _ZN6kernel11kernel_main17h947565f396a80a38E: 0x0000000000080fd4 &lt;+0&gt;: sub sp, sp, #0xc0 0x0000000000080fd8 &lt;+4&gt;: stp x30, x27, [sp, #112] (gdb) c Continuing.</pre> <p>loadコマンドをつかえば、バイナリを動的にメモリ上にロードすることだってできちゃいます。</p> <pre class="code" data-lang="" data-unlink>(gdb) load Loading section .text, size 0x1674 lma 0x80000 Loading section .rodata, size 0x4c5 lma 0x81678 Loading section .got, size 0x10 lma 0x81b40 Loading section .data, size 0x20 lma 0x81b50 Start address 0x0000000000080000, load size 7017 Transfer rate: 63 KB/sec, 1754 bytes/write.</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/raspberry%20pi">raspberry pi</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>にはSRSTピンが生えていないため、<a class="keyword" href="http://d.hatena.ne.jp/keyword/gdb">gdb</a>の<code>monitor reset</code>コマンドを利用してチップをリセットしてロードしたプログラムを再実行させることはできませんが、プログラムカウンタ(pc)を変更することはできるので、代わりに使うといいかもしれません。</p> <pre class="code" data-lang="" data-unlink>(gdb) set $pc=0x80000 (gdb) c</pre> <p>というわけで、とっても便利な<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>を活用して、皆様も楽しいRasPiベアメタル開発の時間をお過ごしください!</p> <h2 id="付録-openocdがうまくいかないとき">付録: openocdがうまくいかないとき</h2> <pre class="code" data-lang="" data-unlink>Error: no device found Error: unable to open ftdi device with vid 0403, pid 6014, description &#39;C232HM-DDHSL-0&#39;, serial &#39;*&#39; at bus location &#39;*&#39;</pre> <p>→そもそも<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>アダプタがPCにつながっていない/認識されていない。</p> <pre class="code" data-lang="" data-unlink>Error: JTAG scan chain interrogation failed: all ones Error: Check JTAG interface, timings, target power, etc. Error: Trying to use configured scan chain anyway... Error: auto0.tap: IR capture error; saw 0x0f not 0x01 Warn : Bypassing JTAG setup events due to errors Error: Invalid ACK (7) in DAP response Error: JTAG-DP STICKY ERROR</pre> <p>→<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>対象のデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の電源が入っていない/まだ起動直後で<a class="keyword" href="http://d.hatena.ne.jp/keyword/JTAG">JTAG</a>が有効化されてない/配線が間違っている/<code>enable_jtag_gpio=1</code>の設定変更が正しく反映されていない。</p> hikalium liumOS 2020年の進化を振り返る hatenablog://entry/26006613666209779 2020-12-17T00:59:46+09:00 2020-12-17T19:53:36+09:00 この記事は自作OS Advent Calendar 2020の「最初の4つの素数の和」日目の記事として作成されました。 liumOSについて liumOSは、NVDIMM(Non-volatile DIMM, 不揮発性メインメモリ)をネイティブにサポートしている、珍しいタイプの自作OSです。2018年7月26日に開発を開始して以来、記事執筆時点で682 commitsを数えるほどに成長しました。主要開発者はhikaliumですが、後述する通り、ここ数ヶ月間はd0iasmさんにも手伝っていただいていました。 2018年には、自作OSからNVDIMMを触る方法について自作OS Advent Cal… <p>この記事は<a href="https://adventar.org/calendars/4954">自作OS Advent Calendar 2020</a>の「最初の4つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>の和」日目の記事として作成されました。</p> <h1>liumOSについて</h1> <p><a href="https://github.com/hikalium/liumos">liumOS</a>は、NVDIMM(Non-volatile DIMM, 不揮発性メインメモリ)をネイティブにサポートしている、珍しいタイプの自作OSです。2018年7月26日に開発を開始して以来、記事執筆時点で682 commitsを数えるほどに成長しました。主要開発者はhikaliumですが、後述する通り、ここ数ヶ月間は<a href="https://github.com/d0iasm">d0iasm</a>さんにも手伝っていただいていました。</p> <p>2018年には、自作OSからNVDIMMを触る方法について自作OS Advent Calendar 2018の記事で紹介しましたので、NVDIMMについて知らないよという方や、興味のある方はそちらもぜひお読みください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2018%2F12%2F17%2F234735" title="自作OSでできる!NVDIMMのつかいかた - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2018/12/17/234735">hikalium.hatenablog.jp</a></cite></p> <p>今年は、かなり色々なものをliumOS上に実装して遊んでいたので、この記事ではそのうちのいくつかについて紹介してみたいと思います。</p> <h1>Adlibを利用した<a class="keyword" href="http://d.hatena.ne.jp/keyword/MIDI">MIDI</a>再生機能</h1> <p>これはOSの中核的な機能ではありませんが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%A4%A5%B9%A5%C9%A5%E9%A5%A4%A5%D0">デバイスドライバ</a>の実装の一環として、<a href="http://bochs.sourceforge.net/techspec/adlib_sb.txt">Adlib</a>という非常に古い<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A6%A5%F3%A5%C9">サウンド</a>デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>のドライバを書いて、さらに<a class="keyword" href="http://d.hatena.ne.jp/keyword/MIDI">MIDI</a>ファイルのパーサを書いて再生できるようにしました。実は中学生の頃に開発していた自作OSでも<a class="keyword" href="http://d.hatena.ne.jp/keyword/MIDI">MIDI</a>ファイルの再生を試みていたことはあるのですが、当時はビープ音で無理やりなんとか和音を出そうとして結局失敗した記憶があり、その当時の<a class="keyword" href="http://d.hatena.ne.jp/keyword/MIDI">MIDI</a>パーサを再利用してN年越しの目標を達成したのでした。</p> <p>デモ動画はこちらです。(音が鳴るので注意。)</p> <iframe width="560" height="315" frameborder="0" allowfullscreen="" src="//www.youtube.com/embed/bhSsYw8JXYQ"></iframe> <p><br><a href="https://youtube.com/watch?v=bhSsYw8JXYQ">liumOS Adlib MIDI再生デモ</a></p> <h1>virtio-netドライバの追加とICMP, <a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>への対応</h1> <p>前菜を楽しんでいただけたところで、メインディッシュですが、なんとliumOSにネットワーク通信機能を追加しました。</p> <p>たとえば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/ping">ping</a>に応答するデモはこちらです。</p> <iframe width="560" height="315" frameborder="0" allowfullscreen="" src="//www.youtube.com/embed/66V8fTTt7KM"></iframe> <p><br><a href="https://youtube.com/watch?v=66V8fTTt7KM">liumOS pingデモ</a></p> <p>冒頭でさらっと流されていますが、なんと<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>その他が自動的に割り当てられている点にも注目です!</p> <p><figure class="figure-image figure-image-fotolife" title="ipコマンドで割り当てられたIPアドレスを確認している図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201217/20201217022248.png" alt="f:id:hikalium:20201217022248p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>ipコマンドで割り当てられた<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>を確認している図</figcaption></figure></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a>ドライバとしては、仮想入出力デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a><a href="https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html">virtio</a>のうちのひとつである、virtio-netを実装しています。また、GPD Micro PCで採用されているRTL8168という<a class="keyword" href="http://d.hatena.ne.jp/keyword/Realtek">Realtek</a>社製の<a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a>についても現在ドライバの実装を進めているところです。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a>通信への対応、ソケット<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>の部分的実装、簡単なブラウザアプリの実装</h1> <p>さて、<a class="keyword" href="http://d.hatena.ne.jp/keyword/ping">ping</a>ができるなら、もうなんでもできますね!だって、パケットを送受信するだけですから。(本当に?)</p> <p>ということで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/UDP">UDP</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>と、ソケット関連<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%B9%A5%C6%A5%E0%A5%B3%A1%BC%A5%EB">システムコール</a>をいくつか実装し、d0iasmさんによって書かれた簡易ブラウザアプリケーションが動くように環境を整備しました。</p> <p>たとえば、このようにliumOS内のクライアントから、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>上で動くサーバーにリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トを投げればHTMLが返ってきますし、</p> <p><figure class="figure-image figure-image-fotolife" title="liumOS内からHTTPのやりとりをしている図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201217/20201217025756.png" alt="f:id:hikalium:20201217025756p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>liumOS内からHTTPのやりとりをしている図</figcaption></figure></p> <p>これをパースして<a class="keyword" href="http://d.hatena.ne.jp/keyword/Markdown">Markdown</a>に整形するという簡易ブラウザまで動いてしまいます!</p> <p><figure class="figure-image figure-image-fotolife" title="同じHTTPのやりとりだが、出力をパースしてMarkdownに整形して出力している簡易ブラウザの図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201217/20201217025918.png" alt="f:id:hikalium:20201217025918p:plain" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>同じHTTPのやりとりだが、出力をパースして<a class="keyword" href="http://d.hatena.ne.jp/keyword/Markdown">Markdown</a>に整形して出力している簡易ブラウザの図</figcaption></figure></p> <p>どうですか?自作OSでも、これくらいなら少し頑張ればできるんです!</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%2BDB%20Press">Web+DB Press</a> Vol.120の特集「自作OS×自作ブラウザで学ぶ Webページが表示されるまで」をd0iasmさんと執筆した</h1> <p>さて、このようなことをしていましたら、ありがたいことに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BB%BD%D1%C9%BE%CF%C0%BC%D2">技術評論社</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%2BDB%20Press">Web+DB Press</a>編集部よりお声がけをいただき、自作OSと自作ブラウザを通して、Webページが表示されるまでの流れを、文字通り上から下まで一通り追ってゆく記事を執筆させていただく機会を得ました。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">12/24発売の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%2BDB%20Press">Web+DB Press</a> Vol.120、ひとつめの特集は<br>「自作OS×自作ブラウザで学ぶ」<br>Webページが表示されるまで<br>ですよ!お楽しみに!!!<br>( <a href="https://twitter.com/d0iasm?ref_src=twsrc%5Etfw">@d0iasm</a> と一緒に書きました!)<a href="https://twitter.com/hashtag/wdpress?src=hash&amp;ref_src=twsrc%5Etfw">#wdpress</a> <a href="https://t.co/VEtxQqRzbG">https://t.co/VEtxQqRzbG</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1336272538826014720?ref_src=twsrc%5Etfw">2020年12月8日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgihyo.jp%2Fmagazine%2Fwdpress%2Farchive%2F2021%2Fvol120" title="WEB+DB PRESS Vol.120" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://gihyo.jp/magazine/wdpress/archive/2021/vol120">gihyo.jp</a></cite></p> <p>Webページが表示されるまでに、HTTPのリク<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%B9">エス</a>トがどのようにしてパケットにまで落とし込まれて、レスポンスとしてのHTMLがどのようなパスを通って運ばれてゆき、最終的に目に見える形になるのか、ということを解説した、合計36ページの特集となっておりますので、面白そう!と思っていただけたなら、ぜひ書店で内容を確認したり、購入して読んでいただけたりしたら大変嬉しく思います。12/24発売です!</p> <p>この特集の概要の紹介や、デモを交えた動画を近日中にアップロードする予定ですので、そちらもお楽しみに!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.youtube.com%2Fchannel%2FUCMsstGhINXdpMqo9tsElCMQ" title="低レイヤーガール - YouTube" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/channel/UCMsstGhINXdpMqo9tsElCMQ">www.youtube.com</a></cite></p> <h1>今後の展望など</h1> <p>やりたいことは無限にあって永遠に楽しめるのが自作OSのよいところですが、ある程度目標を立てておいたほうが物事を進めやすいのは確かです。ということで、いくつかここで私がやりたいと思っていることを書き連ねておくことにします。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>サポートを向上させる</h2> <p>現在のところ、liumOSにはほとんど<a class="keyword" href="http://d.hatena.ne.jp/keyword/GUI">GUI</a>と呼べるものがありません。画面描画を行う<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>はアプリケーションに対して提供されていませんし、入力<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9">インターフェイス</a>についても、ほんの少し前に<a class="keyword" href="http://d.hatena.ne.jp/keyword/PS/2">PS/2</a>マウスのサポートがやっと入ったほどです。そのため、先ほど紹介した特集でも、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CUI">CUI</a>ブラウザを実装するのがやっとの状態でした。</p> <p>せっかくブラウザの下回りができたなら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>で文字を大きく表示したり色を変えたり、なんなら文字列を<code>&lt;blink&gt;</code>させたいですよね?(とはいえ<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blink">blinkタグはすでに廃止</a>されていますが…。)</p> <p>ということで、ある程度の描画がアプリケーション側からできるような仕組みを近いうちに用意し、ついでにブラウザの実装も拡張したいなあと思っています。</p> <h2>RustでOS本体を書き直す</h2> <p>現在のliumOSは<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>で書かれています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>が使えるだけでも<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>に比べれば大きな進歩だったのですが、やはりメモリ安全性という面では<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>と五十歩百歩と言わざるを得ません。最近応用が広がってきたRustであれば、より安全にプログラムを書くことができます。ということで、Rustで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>を書き直すことを現在検討しています。すでに、Rustで書かれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>を従来のliumOSローダーが起動できるところまでは確認しているため、あとは実装するだけという状況なのですが、うまいことインクリメンタルにできないものか、考えつつ現在進めているところです。(まあ、いつか気分が乗った時にえいやっと書き換えることになりそうな気がしますが…。)</p> <h2>ネットワーク機能の拡張</h2> <p>現在のliumOSのネットワークまわりはかなり<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%DB%A5%C3%A5%AF">アドホック</a>に実装されており、複数の<a class="keyword" href="http://d.hatena.ne.jp/keyword/NIC">NIC</a>をうまく扱えない、ソケットの実装がはりぼてすぎる、たまにドライバがこけるなどの問題が発生しています。特に、ドライバを書くというのは自作OSにとって頭の痛い問題ですが、私としてはネットワークドライバほど実装しておいしいものは他にないのではないかと考えています。というのも、基本的な機能としては「パケットを送信する」「パケットを受信する」の2つしかありませんし、ネットワークの先になにがあるかを私たちは意識する必要がないからです。たとえば、自作OSでファイルを保存できるところまで到達しているケースはかなり少ない(liumOSはNVDIMMに対応しているのでなんでも保存できる!…と言い張ることができるかもしれない)ですが、ネットワーク通信さえ対応してしまえば、保存すべきファイルをネットワーク越しに送信するようにすることで、自作OS側でドライバを書かなくて済む可能性が出てきます。(もちろん、各種<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>を実装する必要がありますが…。)あと、自作OS同士が独自の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%C8%A5%B3%A5%EB">プロトコル</a>で通信するのをみてみたい、という気持ちもかなりあります。ということで、おそらくネットワーク周りの機能はそれなりに重点的に進めていくことになるような気がしています。</p> <h1>おわりに</h1> <p>そういうわけで、今年もいろいろな機能がliumOSには生えましたし、今後も生やしていくつもりではいるのですが、ここで大事なことをひとつ。</p> <p>自分が楽しいと思えることをやっていきましょう!最初から完璧なものを作る必要はありません。なにせ、一番のユーザーは自分自身なのですから。</p> <p>自分以外のユーザーが出てきたら、そのときはそのときでまた考えましょう!(なおliumOSにはついに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%D7%A5%EA%B3%AB%C8%AF">アプリ開発</a>者(@d0iasm)が登場したので、大急ぎでテストを書いたりドキュメントの修正をしたりしていました。もちろんこれも楽しいからやってるんですけどね!)</p> <p>ということで、このご時世で家にいる時間も多くなってきていると思いますので、皆様ぜひ暖かい部屋でゆっくりしながら、のんびりとした自作OSライフをお楽しみください!ではでは!</p> hikalium SECCON 2020 OnlineCTF writeup -- SCSBX:Reversing hatenablog://entry/26006613639464241 2020-10-11T20:59:17+09:00 2020-10-11T22:29:14+09:00 概要 今年も例年のように、チームHarekazeの一員として出ました。チームの結果は2123点で11位/579チーム(何らかのFLAGを提出したチーム数)でした。 そのうち、私はSCSBX:Reversingを解いて129ポイントを稼ぎました。(st98さんが一人で1552ポイントも稼いでおり目を回しています。) あと、同じSCSBXをテーマにしたSCSBX:Escapeや、脆弱なkernel moduleの秘孔を突くkstackという問題にも挑戦しましたが、時間内に解くまでにはいたりませんでした。 ということで、挑戦した各問題の解法 or 挑戦のようすを書いておきます。 SCSBX:Reve… <h1>概要</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201011/20201011204310.png" alt="f:id:hikalium:20201011204310p:plain" title="f:id:hikalium:20201011204310p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>今年も例年のように、チーム<a href="https://harekaze.com/">Harekaze</a>の一員として出ました。チームの結果は2123点で11位/579チーム(何らかのFLAGを提出したチーム数)でした。 そのうち、私はSCSBX:Reversingを解いて129ポイントを稼ぎました。(st98さんが一人で1552ポイントも稼いでおり目を回しています。)</p> <p>あと、同じSCSBXをテーマにしたSCSBX:Escapeや、脆弱なkernel moduleの秘孔を突くkstackという問題にも挑戦しましたが、時間内に解くまでにはいたりませんでした。</p> <p>ということで、挑戦した各問題の解法 or 挑戦のようすを書いておきます。</p> <h1>SCSBX:Reversing</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201011/20201011194731.png" alt="f:id:hikalium:20201011194731p:plain" title="f:id:hikalium:20201011194731p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>の公開された独自の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%C8%A5%B3%A1%BC%A5%C9">バイトコード</a>処理系と、それ向けに書かれたアプリケーションのバイナリが与えられています。 そのアプリケーションは、入力がフラグであるか否かを教えてくれるものでした。</p> <pre class="code" data-lang="" data-unlink>$ ./scsbx seccon.bin FLAG: hogehoge Wrong!!</pre> <p>ということで、その処理をみてみれば、どのような入力が期待されているのか、つまりフラグがわかりそうです。ということで、読んでいきましょう。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を読んでみる</h2> <p>ファイルとしてはこんな感じ。</p> <pre class="code" data-lang="" data-unlink>$ ls Makefile instr_logic.cpp main.cpp instr_arith.cpp instr_mem.cpp scsbx.cpp instr_branch.cpp instr_sys.cpp scsbx.hpp</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>で書かれているんですねー。たとえば、<code>scsbx.cpp</code>の中をみてみると、</p> <pre class="code" data-lang="" data-unlink>void SCSBX::__cpu_exec(u8 instr) { u32 val; switch(instr) { /* Memory Operation */ case INS_PUSH: val = *(u32*)(&amp;code[pc+1]); __stack_push(val); pc += 4; break; case INS_POP: __stack_pop(); break; case INS_DUP: __stack_dup(); break; case INS_XCHG: __stack_xchg(); break; case INS_LOAD32: __mem_load32(); break; case INS_LOAD64: __mem_load64(); break; case INS_STORE8: __mem_store8();</pre> <p>という感じで、非常に素直に書かれています。</p> <p>また、<code>DOCS.md</code> というファイルも含まれていたのでみてみると、命令形式についての説明やメモリレイアウトについても書かれていました。めっちゃ親切。</p> <pre class="code" data-lang="" data-unlink>### Instruction Every instruction except for `push` is 1-byte long. `push` accepts a 4-byte value to push into the stack. **SCSBX is proudly open-sourced!** Check the source code for more details.</pre> <pre class="code" data-lang="" data-unlink>0x00000000 +-------------------+ | | | Free Space | 0x55540000 +-------------------+ | Machine Code (R-) | +-------------------+ | | | Free Space | | | 0xfffe0000 +-------------------+ | Stack (RW) | 0xffff0000 +-------------------+ ^^^ user-space ^^^ | Guard Page (--) | 0xffffffff +-------------------+ vvv VM-space vvv | VM instance | | ... |</pre> <p>とりあえず、PUSH命令以外はすべて1バイトのスタックマシンということがわかったので、さくっとディス<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%E9">アセンブラ</a>を書きます。というか、<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を改造して、オプションを渡したらdisasしてくれるようにしました。その出力がこちら。</p> <pre class="code" data-lang="" data-unlink>$ ./scsbx ../seccon.bin -d 00000000: 20 00001000: push 00000005: 20 DEAD0000: push 0000000A: 62: map 0000000B: 20 00000256: push 00000010: 34: call 00000011: 20 0000020A: push 00000016: 34: call 00000017: 20 47414C46: push 0000001C: 20 DEAD0004: push 00000021: 28: store32 00000022: 20 0000203A: push 00000027: 20 DEAD0008: push 0000002C: 27: store16 0000002D: 20 00000006: push 00000032: 20 DEAD0004: push 00000037: 61: write 00000038: 20 00000040: push 0000003D: 20 DEAD000A: push 00000042: 60: read 00000043: 20 00000008: push 00000048: 20 0000010E: push ...</pre> <p>やっぱりスタックマシンだし長いですね。というわけで、じっとこれを見つめてデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B4%A4%C3%A4%B3">ごっこ</a>をします。</p> <p>私なりのやり方としては、大体以下のような手順を踏みました。</p> <ol> <li>分岐命令を境に、命令列をブロックに分ける。</li> <li>上から辿っていって何をやっているかお気持ちを理解する</li> <li>複雑な部分では、スタックを書いて追いながらロジックを推定する</li> </ol> <p>たとえばこんな感じに、スタックの使われ方を書いていったり、</p> <pre class="code" data-lang="" data-unlink>&lt;check_loop()&gt; /* [0] k [1] v */ 00000135: 20 00000000: push 0000013A: 22: dup 0000013B: 20 00000001: push 00000140: 20 00000001: push 00000145: 23: xchg 00000146: 41: sub /* [0] k - 1 [0] k [1] v */ 00000147: 20 00000008: push 0000014C: 42: mul /* [0] (k - 1) * 8 [0] k [1] v */ 0000014D: 20 DEAD000A: push 00000152: 40: add /* [0] (k - 1) * 8 + 0xDEAD000A [0] k [1] v */ ...(省略) 00000183: 20 00000001: push 00000188: 23: xchg /* [2] k [0] v | (*p - *q) | (*(p + 4) - *(q + 4)) */ 00000189: 20 00000001: push 0000018E: 20 00000001: push 00000193: 23: xchg 00000194: 41: sub /* [2] k - 1 [0] v | (*p - *q) | (*(p + 4) - *(q + 4)) */</pre> <p>これを元に<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>ベースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BC%BB%F7%A5%B3%A1%BC%A5%C9">擬似コード</a>に落とし込んだりしてみました。</p> <pre class="code" data-lang="" data-unlink>int main(int argc, char *argv) { // 00000000 // map [DEAD0000 - DEAD1000) InitEncFlag(); // 0000020A *(uint32_t *)&amp;mem[0] = 0x06D35BCD; // 00000017 // read 0x40 bytes into *0xDEAD000A strncpy(&amp;mem[0xA], &#34;SECCON{[\x20-\x7e]+}&#34;, 0x40); uint32_t i = 8; // pushed at +00000043 // 0000010E // [] i while(i) { // 0000004E // 000000DD // Stack after 00000097 // []: *((8-i) * 8 + 0xDEAD000E) = v1 // []: *(8-i) * 8 + 0xDEAD000A) = v2 // []: (8-i) * 8 + 0xDEAD000A // []: (8-i) * 8 + 0xDEAD000E // []: i uint32_t v1 = *((8-i) * 8 + 0xE + mem); uint32_t v2 = *((8-i) * 8 + 0xA + mem); uint32_t p = 3; // pushed at +00000098 // 000000DD while(p) { // 000000A3 // []: p // []: v1 // []: v2 p--; uint32_t c = v2; v2 = v1; v1 = random_num(v1) ^ c; } // 000000F3 // []: p // []: v1 // []: v2 // []: (8-i) * 8 + 0xDEAD000A // []: (8-i) * 8 + 0xDEAD000E // []: i *((8-i) * 8 + 0xE + mem) = v1; *((8-i) * 8 + 0xA + mem) = v2; i--; // 00000102 - 0000010D // 0000010E }; // check if flag_buf is same as flag_encrypted ... }</pre> <p>さて、デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>の気持ちを理解したところで、このプログラムは大体以下のような処理を行っていることがわかりました。</p> <ol> <li>作業用のメモリ領域[0xDEAD0000 - 0xDEAD1000)をmapする</li> <li>そのメモリ領域に符号化されたフラグを展開する(0xDEAD004A から0x40バイト)</li> <li>0xDEAD0000番地に値0x06D35BCDを格納する(おそらく何らかのシード値、後のロジックで使われる)</li> <li>ユーザーからの入力を受け取る(0x40バイト、これは0xDEAD000A番地から0x40バイトの空間に格納される)</li> <li>上の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BC%BB%F7%A5%B3%A1%BC%A5%C9">擬似コード</a>に書いたような処理を行って、ユーザーからの入力を符号化する</li> <li>符号化した入力(0xDEAD000Aからの0x40バイト)と、展開しておいた符号化済みのフラグ値(0xDEAD004Aからの0x40バイト)を比較する</li> <li>それらが一致したらCorrect, 一致しなければWrong!!と出力して終了する</li> </ol> <p>さて、肝心のstep5の処理ですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%BC%BB%F7%A5%B3%A1%BC%A5%C9">擬似コード</a>としてはこんな感じです。(enc()がその処理)</p> <pre class="code" data-lang="" data-unlink>uint32_t random_num(uint32_t v) { // 00000216 uint32_t *dead0000 = (uint32_t *)&amp;mem[0]; *dead0000 = (*dead0000 * 0x77F - 0x32A) % 0x0x305EB3EA; return ~(v ^ *dead0000); } void enc() { uint32_t i = 8; // pushed at +00000043 // 0000010E while(i) { // 0000004E // 000000DD uint32_t v1 = *((8-i) * 8 + 0xE + mem); uint32_t v2 = *((8-i) * 8 + 0xA + mem); uint32_t p = 3; // pushed at +00000098 // 000000DD while(p) { // 000000A3 p--; uint32_t c = v2; v2 = v1; v1 = random_num(v1) ^ c; } // 000000F3 *((8-i) * 8 + 0xE + mem) = v1; *((8-i) * 8 + 0xA + mem) = v2; i--; // 00000102 - 0000010D // 0000010E } }</pre> <p>要するに、8バイトを1セットとして符号化するのを8回くりかえすことで、8*8 = 64 = 0x40バイトの領域を符号化しているわけです。 また、random_num()と仮においた処理は、0xDEAD0000番地のメモリ内容という状態を持っているため、呼び出しには副作用があります。 とはいえ、基本的にやっていることは、その8バイトの中で前後4バイトずつの部分をxorしているだけで、入力と出力は各桁ごとに独立に変化します。 結局、random_num()の状態に注意しつつ、8バイトずつのセットの各文字を順に確定させてゆけば、フラグがわかりそうです。(これなら最大でも256 * 8 * 8通り調べればいけますね。)</p> <p>というわけで、このアイディアをかんたんな<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>のプログラムに落とし込みました。</p> <pre class="code" data-lang="" data-unlink>#include &lt;stdint.h&gt; #include &lt;stdio.h&gt; uint32_t dead0000 = 0x06D35BCD; uint32_t random_num(uint32_t v) { // 00000216 dead0000 = (dead0000 * 0x77F - 0x32A) % 0x305EB3EA; return ~(v ^ dead0000); } uint64_t enc(uint64_t v) { uint32_t v1 = v &gt;&gt; 32; uint32_t v2 = v; uint32_t p = 3; // pushed at +00000098 while (p) { p--; uint32_t c = v2; v2 = v1; v1 = random_num(v1) ^ c; } return ((uint64_t)v1 &lt;&lt; 32) | v2; } uint8_t mem[64]; void InitEncFlag() { // 00000256 *(uint32_t *)&amp;mem[4 * 0x0] = 0x46761223; *(uint32_t *)&amp;mem[4 * 0x1] = 0x54BEA5C5; *(uint32_t *)&amp;mem[4 * 0x2] = 0x7A22E8F6; *(uint32_t *)&amp;mem[4 * 0x3] = 0x5DB493C9; *(uint32_t *)&amp;mem[4 * 0x4] = 0x055D175E; *(uint32_t *)&amp;mem[4 * 0x5] = 0x022FCD33; *(uint32_t *)&amp;mem[4 * 0x6] = 0x42C46BE6; *(uint32_t *)&amp;mem[4 * 0x7] = 0x6D10A0E8; *(uint32_t *)&amp;mem[4 * 0x8] = 0x53F4C278; *(uint32_t *)&amp;mem[4 * 0x9] = 0x7279EC2A; *(uint32_t *)&amp;mem[4 * 0xA] = 0x5491FB39; *(uint32_t *)&amp;mem[4 * 0xB] = 0x49AC421F; *(uint32_t *)&amp;mem[4 * 0xC] = 0x49AB3A37; *(uint32_t *)&amp;mem[4 * 0xD] = 0x47855812; *(uint32_t *)&amp;mem[4 * 0xE] = 0x5718BB05; *(uint32_t *)&amp;mem[4 * 0xF] = 0x0540FB5B; } int main(int argc, char *argv[]) { InitEncFlag(); char buf[64 + 1] = &#34;SECCON{........&#34;; for (int i = 0; i &lt; 8; i++) { for (int k = 0; k &lt; 8; k++) { for (char c = 0x20; c &lt;= 0x7E; c++) { buf[k] = c; uint32_t prev_dead0000 = dead0000; uint64_t e = enc(*(uint64_t *)buf); uint8_t *p = (uint8_t *)&amp;e; dead0000 = prev_dead0000; if (p[k] == mem[k + i * 8]) { break; } } } uint64_t e = enc(*(uint64_t *)buf); printf(&#34;%.8s&#34;, buf); } return 0; }</pre> <p>気をつけるべき点は、forの中でencを実行する際に、毎回dead0000の内容を戻しているところですね。(少し冗長ですが色々ためしていたせいである。)</p> <p>というわけで、以下のような出力を得ました。</p> <pre class="code" data-lang="" data-unlink>$ ./solve2 SECCON{TfuRYYVaz8Us696t3JWNxZZPsXEmdL7cCmgzpgxXKarUOnIwhSj9tQ}~~</pre> <p>SECCON{の後にはTがきそう(きっと英語のメッセージ的にTheとかがきそうだから)と思っていて、最初の8桁だけ試してTがでてきてわーいと思っていたのですが、全部出してみたら乱数フラグでちょっと意外でした。(ちゃんと通ってほっとした。)</p> <h3>追記</h3> <p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>はFeistel構造と呼ばれるものらしい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fja.wikipedia.org%2Fwiki%2FFeistel%25E6%25A7%258B%25E9%2580%25A0" title="Feistel構造 - Wikipedia" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://ja.wikipedia.org/wiki/Feistel%E6%A7%8B%E9%80%A0">ja.wikipedia.org</a></cite></p> <h1>SCSBX:Escape</h1> <p>ところでこのSCSBX(SecCon SandBoX), reversingだけでなくsandboxの問題としても登場していました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201011/20201011202618.png" alt="f:id:hikalium:20201011202618p:plain" title="f:id:hikalium:20201011202618p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>こちらは、リモートで動いているSCSBXにいい感じのバイナリを送りつけて、思い通りの動きをさせてshellをゲットしような!という問題だったのだと思います。</p> <p>SCSBXの説明文にこんな一文がありますが、</p> <pre class="code" data-lang="" data-unlink>### Direct Memory Access SCSBX allows the program to directly access to the host memory. This may sound dangerous but the program can only use the 32-bit address space. Since SCSBX runs on a 64-bit machine with PIE enabled, there&#39;s no way the user can read/write the VM memory directly.</pre> <p>明らかにこれはアヤシイ!と思いますよね。というわけで、じっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を見つめると、</p> <pre class="code" data-lang="" data-unlink>void SCSBX::__sys_unmap() { u64 address = ((u64)__stack_pop()) &amp; ~0xfff; __assert_address_valid(address); for(auto itr = memmap.begin(); itr != memmap.end(); ++itr) { if (address == itr-&gt;first) { memmap.erase(itr); munmap((void*)address, itr-&gt;second); return; } } throw MEMORY_ERROR; }</pre> <p>ほう、munmapの戻り値を確認しないとは勇気がありますね?というところを見つけられます。これは何に役立つかと言うと、メモリマップで言う</p> <pre class="code" data-lang="" data-unlink>0x00000000 +-------------------+ | | | Free Space | 0x55540000 +-------------------+ | Machine Code (R-) | +-------------------+ | | | Free Space | | | 0xfffe0000 +-------------------+ | Stack (RW) | 0xffff0000 +-------------------+ ^^^ user-space ^^^ | Guard Page (--) | 0xffffffff +-------------------+ vvv VM-space vvv | VM instance | | ... |</pre> <p>Guard Pageを除去するのに使えます。というのも、このGuard Pageは、実際にmapされているわけではなく、</p> <pre class="code" data-lang="" data-unlink>SCSBX::SCSBX(u8 *_code, u32 _size) { /* Guard page */ memmap.push_back(std::make_pair((u64)STACK_BASE + (u64)STACK_SIZE_INIT, 0x100000000 - (u64)STACK_BASE - (u64)STACK_SIZE_INIT)); }</pre> <p>という感じで<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a>の初期化時に「確保済みのメモリ領域」として予約されているだけなのです。この結果として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a>はこの領域にアクセスするとマップされていないのでSEGVがおきるし、マップしようにもマップ済みなのでmapを実行できない…はずなのですが、先ほどのようにmunmap命令が実行されると、munmapの結果にかかわらずこのmemmapというリストから除去が行われるため、なんとこの領域をmunmapしてから再度<a class="keyword" href="http://d.hatena.ne.jp/keyword/mmap">mmap</a>すれば、普通にアクセスできるようになってしまうというバグがあったわけです。</p> <p>で、ここにアクセスできると何がやばいかというと、Stackが伸びていくとやがてこのGuardPageにあたり、さらにそこを超えると<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a> instance、つまりクラスSCSBXの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>が確保されている領域を上書きできてしまうのです。</p> <p>というわけで、たとえばこうすれば</p> <pre class="code" data-lang="" data-unlink> // unmap guard page instr_push(0xffff0000); instr_unmap(); // map again instr_push(0x00010000); instr_push(0xffff0000); instr_map();</pre> <p>あとはstackをばんばん伸ばすだけでやがてこの構造体を上書きできるようになります。</p> <pre class="code" data-lang="" data-unlink>class SCSBX { private: /* fields */ std::vector&lt;std::pair&lt;u64, u32&gt;&gt; memmap; u32 pc; int status; u8* code; u32* stack; u32 code_size; u32 capacity; u32 top; ... virtual void __assert_address_valid(u64 address); virtual void __assert_range_valid(u64 address, u64 size); virtual void __assert_resource_available(u64 address, u32 size); ... };</pre> <p>しかもこの構造体、virtual関数としてアドレス範囲チェック系の重要な関数のポインタが記録されている場所でもあるので、ここをいい感じにRETを指すポインタように上書きすれば、チェックを全部回避することも、さらに任意のアドレスに実行を飛ばすこともできます。</p> <p>…というところまでわかって、時間切れでした。ざんねん。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>が得意ではないので、hashのチャレンジレスポンスを解きつつ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A4%A5%ED%A1%BC%A5%C9">ペイロード</a>を突っ込む<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を将来また書かなくてもいいようにここに貼っておきます。</p> <pre class="code" data-lang="" data-unlink>from pwn import * import itertools import hashlib import string import sys print(sys.argv[1]) f = open(sys.argv[1], &#34;rb&#34;) attack_bytes = f.read() table = string.ascii_letters + string.digits + &#34;._&#34; p = remote(&#39;pwn-neko.chal.seccon.jp&#39;, 19001) ret = p.recvline().decode(&#34;utf-8&#34;) # ret = &#39;sha256(&#34;????LFx0jSq8mYA4oZC_.Kuw&#34;) = ca67aa308662f39b8e294a99120588102a94 hashval = ret.split(&#34;=&#34;)[-1].strip() print(hashval) suffix = ret.split(&#34;\&#34;&#34;)[1].replace(&#34;?&#34;, &#34;&#34;) print(suffix) for v in itertools.product(table, repeat=4): if hashlib.sha256((&#39;&#39;.join(v) + suffix).encode()).hexdigest() == hashval: prefix = &#39;&#39;.join(v) break else: print(&#34;[-] Solution not found :thinking_face:&#34;) print(&#34;[+] Prefix = &#34; + prefix) p.sendline(prefix) p.recvuntil(&#39;size&#39;) p.sendline(str(len(attack_bytes))) p.recvuntil(&#39;code&#39;) p.sendline(attack_bytes) p.interactive()</pre> <h1>kstack</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20201011/20201011204833.png" alt="f:id:hikalium:20201011204833p:plain" title="f:id:hikalium:20201011204833p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>なんか<code>/proc/stack</code>というファイルに対するioctlを生やすkernel moduleが入ったマシンにつながるので、そいつのバグを突いて権限昇格しようね、という問題だったようです。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>で実行できるようイメージと引数の書かれた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%A7%A5%EB%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">シェルスクリプト</a>が一緒に配られていて、めちゃくちゃ親切でうれしかったです。</p> <p>ioctlの仕様としては、ioctl(fd, CMD_PUSH, &amp;<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>)を発行すると、その値がユーザーランドから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>空間のスタック(実体は各要素がkmalloc(<a class="keyword" href="http://d.hatena.ne.jp/keyword/GFP">GFP</a>_KERNEL)で確保されたLinked List)に格納され、ioctl(fd, CMD_POP, &amp;<a class="keyword" href="http://d.hatena.ne.jp/keyword/value">value</a>)を発行すると、その<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>空間のスタックからユーザーランドに値がコピーされていく、というものでした。 ちなみに、そのLinked Listの各要素には、格納したタスクのtgidが一緒に記録されていて、あるtgidが記録したデータに対する操作はそのtgid<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>かできないようになっていました。</p> <p>これについては全然進捗がなくて、複数タスクから同時にPOP処理をかけたら、解放された領域を指し続けるLinked Listが構成できそうとか、pidがぐるっと一周したらどうなる?とか色々あったのですが、結局時間も割けなくてとけませんでした。もっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>に詳しくなりたいですね。</p> <h1>作問者による簡易解説ツイート</h1> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SCSBX:Reversing: Feistel構造<br>SCSBX:Escape: Guard Pageがunmapできる。pushに範囲チェックが無いので<a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a> instanceを破壊できる。偽のstd::<a class="keyword" href="http://d.hatena.ne.jp/keyword/vector">vector</a>&lt;std::pair&gt;に向けて範囲外read/writeが可能になる。libc baseはstack base,top上書き後にGOTの値を<a class="keyword" href="http://d.hatena.ne.jp/keyword/dup">dup</a>して取得。あとはvtable書き換え。</p>&mdash; pwnyaa (@pwnyaa) <a href="https://twitter.com/pwnyaa/status/1315176054063992832?ref_src=twsrc%5Etfw">2020年10月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">pwarmup: stdoutが閉じてるのでシェルコード実行。stdinを<a class="keyword" href="http://d.hatena.ne.jp/keyword/dup">dup</a>するなりリバースシェル作るなりご自由に。<br>kstack: userfaultfdでrace。seq_operationsなどでRIPを取る。<a class="keyword" href="http://d.hatena.ne.jp/keyword/SMAP">SMAP</a>無効なのでuser-landでROP。<br>encryptor: libc-2.31でargv[0] leak。同じオプションを何度も指定できるのでstrcpyでNULLを量産。</p>&mdash; pwnyaa (@pwnyaa) <a href="https://twitter.com/pwnyaa/status/1315175664027201536?ref_src=twsrc%5Etfw">2020年10月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h1>感想</h1> <p>バイナリおいしい!あと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a>むずかしい…。</p> <p>全体的に、問題のクオリティがかなり上がっているという印象を受けました。とてもよいことだと思います。それに、何より問題を解くのが楽しかったです。(可視化とかも面白かった。)</p> <p>運営のみなさん本当にお疲れ様でした!ありがとうございましたー!</p> hikalium ISUCON10予選 meguryohikaの記録 hatenablog://entry/26006613627061989 2020-09-12T23:57:59+09:00 2020-09-13T02:01:52+09:00 ISUCON10の予選にmeguryohikaとして @megumish_unsafe, @systemctl_ryoto と共に出たのでその記録です。 結果としては、初期スコア500点台から、900点台の、1000点に届きそうかな?というところまでは行けたものの、最後のベンチマーク前に複数台構成にしようとして失敗した結果スコアがつかずおしまいでした。来年もまたやりたいですね! ISUCONは参加者だけじゃなくて運営にも降りかかる… 午前10:00から試合開始ということで、前日は人々とイカをやるのも午前1時までにとどめておき、無事健康的な午前起床を達成しました。 いい感じに睡眠からwake-U… <p><a href="http://isucon.net/archives/54704557.html">ISUCON10の予選</a>にmeguryohikaとして <a href="https://twitter.com/megumish_unsafe">@megumish_unsafe</a>, <a href="https://twitter.com/systemctl_ryoto">@systemctl_ryoto</a> と共に出たのでその記録です。</p> <p>結果としては、初期スコア500点台から、900点台の、1000点に届きそうかな?というところまでは行けたものの、最後の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>前に複数台構成にしようとして失敗した結果スコアがつかずおしまいでした。来年もまたやりたいですね!</p> <h1>ISUCONは参加者だけじゃなくて運営にも降りかかる…</h1> <p>午前10:00から試合開始ということで、前日は人々と<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%AB">イカ</a>をやるのも午前1時までにとどめておき、無事健康的な午前起床を達成しました。</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いい感じに睡眠からwake-Upするコンテスト、勝利した(起床成功)。</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1304573365626134528?ref_src=twsrc%5Etfw">2020年9月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ところが、その少しまえに、こんなツイートが運営から…</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ISUCON10 オンライン予選について重要なお知らせです。参加者用サポートチャットで共有いたしましたが、環境構築に想定以上の時間がかかっており予定していた10時の開始は難しく現在のところ12時開始となる見込みです。状況についてはまたあらためてアナウンスいたします。 <a href="https://twitter.com/hashtag/isucon?src=hash&amp;ref_src=twsrc%5Etfw">#isucon</a></p>&mdash; ISUCON公式 (@isucon_<a class="keyword" href="http://d.hatena.ne.jp/keyword/official">official</a>) <a href="https://twitter.com/isucon_official/status/1304566981010448384?ref_src=twsrc%5Etfw">2020年9月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>ということで、私の目覚める前からISUCONは始まっていたようです。私たちの開始は昼ごろまで遅れたけれど。(運営のみなさんお疲れ様でした!)</p> <h1>正午までの暇を持て余して環境が整う</h1> <p>2時間の余裕を得た我々は、「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%F3%C5%D9%BF%B2">二度寝</a>するなよ!」というネタをやったり、眠気覚ましにご飯を買いにいく人々が出たりと自由な雰囲気が漂っていました。</p> <p>私も、あまりにも暇だったので、ちょうど横にある<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>マシンを、負荷をかけている際のCPU統計などを表示するのに適したようにセットアップしたいなあという気持ちになって、<code>apt update</code>したり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/NVIDIA">NVIDIA</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GPU">GPU</a>ドライバを入れたりしていました。(なんとドライバを入れていなかったので、1024*768の解像度になっていた…これでは流石にきついと思ったので急いでセットアップした。)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ちょっと頑張っているようで、実際にはただ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>時のログを流しているだけの映像(でも見やすかった)。<a href="https://twitter.com/hashtag/ISUCON?src=hash&amp;ref_src=twsrc%5Etfw">#ISUCON</a> <a href="https://t.co/KDsTJlQEcE">pic.twitter.com/KDsTJlQEcE</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1304760237660889088?ref_src=twsrc%5Etfw">2020年9月12日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <p>そんなわけで、少し環境がリッチになったあたりで、試合開始が12:20からになるとの連絡が。やっていきましょう!</p> <h1>試合開始…からのポータルが<a class="keyword" href="http://d.hatena.ne.jp/keyword/503%20Service%20Unavailable">503 Service Unavailable</a></h1> <p>我々はGoで実装を進めるつもりだった&amp;初期実装がGoと書いてあったので、早速ベンチマーカーを回そうとしたところ…なんとポータルが503に。ISUCONむずかしいね…。</p> <p>というわけで、しばらくベンチマーカーの結果は拝めそうになかったので、megumish氏は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>やリソースの退避とデプロイ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>の作成を、ryotoさんは<a class="keyword" href="http://d.hatena.ne.jp/keyword/bot">bot</a>を弾くnginx configをさっと書いてくれたり、ソースを読んで<a class="keyword" href="http://d.hatena.ne.jp/keyword/SQL">SQL</a>的にヤバそうなところがないかをしらべてくれたりしていました。私はアプリを実際に触ってみて、遅い部分とか面白い部分がないかをしらべてみていました。「なぞって検索」なる、地図上に領域を描いて物件を検索できるページがあったのにはびっくりしました。また、今回は前回までと異なり、サイトへのログインという概念がなかったため、その点でも度肝を抜かれました。(ついつい<code>/admin</code>が存在しないか調べてしまったが、なかった…。)</p> <h1>14:00の定<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BB%FE%CA%F3">時報</a>告</h1> <p>前回までの反省と、チームでこれまで練習してきたことを生かして、今回は1時間ごとにさくっと進捗共有会をすることにしました。そして、進捗共有がおわったら、強制的に5分間休憩タイムをとることにしていました。これは体力を消耗しないという点では非常によい戦略だったと思います。(今までは終盤になると、精神的にもかなり疲れがきていたのですが、今回は最後までゆったりできたので割とおすすめです。)</p> <p>このあたりで、megumish氏がデプロイ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を完成させていて、次はredisを入れてキャッシュできるものはやっていこうか、という流れになっていました。 ryotoさんは<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の各エンドポイントをみ終わって、いくつか修正できそうな点がみつかったので直していく、という話になっていました。</p> <p>私は、やっと初のベンチを走らせてみて、nginxのログをkataribeでフォーマットしてどのエンドポイントを直すのがよさそうか議論する材料を用意しました。</p> <pre class="code" data-lang="" data-unlink>Top 20 Sort By Total Count Total Mean Stddev Min P50.0 P90.0 P95.0 P99.0 Max 2xx 3xx 4xx 5xx TotalBytes MinBytes MeanBytes MaxBytes Request 105 40.860 0.3891 0.4355 0.046 0.178 1.085 1.397 1.698 2.000 103 0 2 0 1700275 0 16193 33967 POST /api/estate/nazotte HTTP/1.1 411 33.686 0.0820 0.0246 0.031 0.078 0.115 0.123 0.151 0.206 411 0 0 0 4989248 12139 12139 12153 GET /api/chair/low_priced HTTP/1.1 411 31.674 0.0771 0.0266 0.032 0.072 0.115 0.127 0.155 0.182 411 0 0 0 5500577 13383 13383 13398 GET /api/estate/low_priced HTTP/1.1 86 14.241 0.1656 0.0457 0.087 0.157 0.234 0.247 0.271 0.271 86 0 0 0 1429937 16627 16627 16642 GET /api/estate/search?page=0&amp;perPage=25&amp;rentRangeId=1 HTTP/1.1 67 10.303 0.1538 0.0388 0.093 0.138 0.213 0.223 0.259 0.259 67 0 0 0 1124707 16786 16786 16801 GET /api/estate/search?page=0&amp;perPage=25&amp;rentRangeId=2 HTTP/1.1 72 10.238 0.1422 0.0348 0.094 0.132 0.194 0.205 0.230 0.230 72 0 0 0 1199601 16660 16661 16682 GET /api/estate/search?page=0&amp;perPage=25&amp;rentRangeId=0 HTTP/1.1</pre> <p>トータルでかかった時間としては、やはり「なぞって検索」が重く、次いで物件と椅子の安い順に上位20件をリストアップするlow_pricedが、一回一回は重くないものの、回数が多いためけっこう負荷になっていることがわかりました。あとは、検索部分が重く、今回のサービスの検索では、かなり多種多様な条件を指定できることがわかっていたので、何らかの高速化が必要だろうね、という話になりました。</p> <p>例えば、searchで指定する条件には、各物件や椅子の属性(features)というのがあって、これはDBにはカンマ区切りの文字列として格納されているのですが、検索時にはそれらのAND条件を指定できる、というもので、当初の実装では全件リードが走っている状態になっており、まあ重いのは致し方ないかな、という感じでした。</p> <p>改善のアイディアとしては、featuresの各要素は固定で50件であることから、各属性に対応するboolのカラム50列をDBに追加して、ついでにindexも貼ってあげればいい感じになるんじゃないか?と考えて、以後私はそれに取り組むことにしました。</p> <p>ちなみに、初期状態でのベンチ終了時点では、データが3万件それぞれのテーブル(chair, estate)に入っており、初期データには2万9500件入っている、ということがわかっていました。なので、実行時に動的に増加する分は、最初は500件ということです。(おそらく、負荷レベルが向上すると、ここが増えたのでしょうが、残念ながらそこまで行きつきませんでした…。)</p> <p>また、単一サーバー(1 core, 2GB RAM)でDB, Webアプリを同時に動かしている状態で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>をかけても、CPU時間は100%に張り付く一方、メモリ消費量は500MBもいかない程度で、swapも全く発生していないという点に気付きました。かなりCPUに集中した負荷がかかっていたようです。当初、私はこれが<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>のメモリ設定が厳しすぎるせいだと考えて、緩和する設定を入れてみたのですが、残念ながら全く使用量が増えなかったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DC%A5%C8%A5%EB%A5%CD%A5%C3%A5%AF">ボトルネック</a>は別の部分にあったようです。</p> <h1>15:00の定期報告</h1> <p>このあたりで、megumish氏はGET chair/low_pricedの結果をキャッシュできないか奮闘していました。</p> <p>ryotoさんは、全く貼られていなかったindexをDBに貼ったところ、100点程度のスコア向上がみられたと報告していました。</p> <p>また、なぞって検索に関して、矩形で大まかに物件をフィルタしたあと、その各物件に対して、<a class="keyword" href="http://d.hatena.ne.jp/keyword/GIS">GIS</a>関連の関数を用いて、描かれたポリゴンの内部にその物件が存在するか否かをチェックしているということがわかり、これをDBに毎回投げるのではなく、Goの側でうまく処理できないかということを検討していました。</p> <p>私は、先ほど言った<a class="keyword" href="http://d.hatena.ne.jp/keyword/MySQL">MySQL</a>周りのチューニングが効果ゼロだったことを報告して、もしかするとDBやアプリを複数サーバーに分散させる必要があるのかもしれないと言いつつ、とりあえずfeaturesをbooleanでDBの複数カラムに格納するものに着手するという話になっていました。</p> <h1>16:00の定期報告</h1> <p>megumish氏は、キャッシュの大まかな実装はできたけれど、うまくベンチが通らず四苦八苦していました。</p> <p>ryotoさんは、椅子を購入すると、物件がrecommendされる(椅子が通るような玄関の間口をもつ家がリコメンドされるシステムだった!)機能のぶぶんを、事前にテーブルを作成することで高速化できないか挑戦していました。</p> <p>私は、chairのfeaturesをカラム化することを引き続き挑戦していました。</p> <h1>17:00</h1> <p>ほぼ同上。だんだんつらくなってくるね。</p> <p><figure class="figure-image figure-image-fotolife" title="縦に長すぎるchairのschemaの図(実際にはf50まで続いたあと、さらに同じ個数のindexが張られている)"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20200913/20200913000124.png" alt="f:id:hikalium:20200913000124p:plain" title="f:id:hikalium:20200913000124p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>縦に長すぎるchairのschemaの図(実際にはf50まで続いたあと、さらに同じ個数のindexが張られている)</figcaption></figure></p> <h1>18:00</h1> <p>megumish氏は、キャッシュをするのはいいけれど、レースコンディションがおきたらどうなるんだろう?という問題に頭を悩ませていました。</p> <p>ryotoさんは、椅子に合った不動産をおすすめする部分の改善目処がつきそうという報告をしており、それが終わり次第、なぞって検索に取り掛かるという目標を掲げていました。</p> <p>私は、featuresをカラムにし終わったものの、なぜか<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>が通らない問題で時間をつぶしていました。(サーバーにデプロイしてみるとうまく動いているように見えた。)</p> <p>糖分が足りなくなってきたので、ここらへんでクレープをたべました。おいしかったです。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20200912/20200912233946.jpg" alt="f:id:hikalium:20200912233946j:plain" title="f:id:hikalium:20200912233946j:plain" class="hatena-fotolife" itemprop="image"></span></p> <h1>19:00</h1> <p>megumish氏の実装のバグが取れたとの報告。<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a>が正しく吐けていなかったみたい。とりあえずうまくいったら、次は複数台構成の検討に入るとのこと。</p> <p>ryotoさんは、物件おすすめ機能をあきらめました。というのも、冷静に考えると、事前計算をする処理はかなり重く、また椅子や物件を追加する<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>の時間制限はわりと厳しかったため、時間内に事前計算を終わらせられそうにないというのが理由でした。</p> <p>今思えば、全部を事前計算せずとも、一度計算したものをキャッシュしておく、などの方策がとれたかもしれないなあ、という感想が浮かんできました。(後から振り返るとそういうアイディアが思いつく。)</p> <p>私は、クレープの糖分をもってしてもバグを解決できず、なんでだーと頭を抱えていました。</p> <h1>さいご</h1> <p>最後ぎりぎりになって、ryotoさんがなぞって検索のジオメトリ計算の部分を<a class="keyword" href="http://d.hatena.ne.jp/keyword/golang">golang</a>に持ってくることに成功し、これで+300程度になりました。</p> <p>さらに、私も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>が失敗する理由に気付き(デプロイ時に走るDB初期化と、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>時に走るinitialize/内でのDB初期化で異なるデータを流し込んでいた)、なんとかマージに成功。</p> <p>最終的に、これでスコアが900点ちょい出たのですが、複数台構成を試そうとしてぎりぎりまでryotoさんが頑張ったものの、間に合わず終了時刻を迎えました。いやはや、よくがんばりました…。</p> <h1>反省点</h1> <ul> <li>複数台構成を練習時にもあまりできておらず、本番でも手間取って間に合わずじまいになってしまった。練習でできないことは本番でもできないよ!</li> <li>当初リストアップしていた修正できそうな点のうち、ひとつを見過ごしてしまっていた。(終わった後に気づいた。) <ul> <li>報告会を定期的にしていたのは非常によかったが、ToDoの管理が不十分だった。見ないToDoに意味はないよ!</li> </ul> </li> <li>複数台構成の件にもつながるが、本番サーバー以外に実行環境を用意できていれば、もう少し開発を効率的に行えたかもしれない。</li> </ul> <h1>まとめ</h1> <p>来年はさらに準備して望みたい…またがんばりましょう!おつかれさまでした!</p> <p><figure class="figure-image figure-image-fotolife" title="14:30頃のつかの間の15位の図"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20200912/20200912235608.png" alt="f:id:hikalium:20200912235608p:plain" title="f:id:hikalium:20200912235608p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>14:30頃のつかの間の15位の図</figcaption></figure></p> <p>追記: チームメンバーのryotoさんとツイート被りしていたことが判明(終わるまで全く気づかなかった)(みんな考えることは同じである)</p> <p><blockquote data-conversation="none" class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いい感じにWake Upコンテスト予選突破です</p>&mdash; Ryoto (@systemctl_ryoto) <a href="https://twitter.com/systemctl_ryoto/status/1304562397340823552?ref_src=twsrc%5Etfw">2020年9月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> hikalium C言語から0番地へアクセスする方法についての個人的まとめ hatenablog://entry/26006613512867500 2020-02-15T12:09:42+09:00 2020-02-15T18:34:57+09:00 発端はuchan_nos氏によるこのツイートでした。 C言語で、本当にメモリの0番地にデータを書きたいときはどうすりゃええの?— うー@技術書典8 Day1う31 BitNOS (@uchan_nos) 2020年2月12日 それに対する私のリプライ: uint8_t *p = 1; p--; *p = v;— hikalium (@hikalium) 2020年2月12日 私はこれで話が終わると思っていたのだが、どうやらそうではなかったらしく、色々な視点からの意見が加わりながら、話は混沌を極めたのでした…。 ということで、ここに私のこのツイートに対しての見解とか、わかったことをまとめておこう… <p>発端はuchan_nos氏によるこのツイートでした。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>で、本当にメモリの0番地にデータを書きたいときはどうすりゃええの?</p>&mdash; うー@技術書典8 Day1う31 BitNOS (@uchan_nos) <a href="https://twitter.com/uchan_nos/status/1227517616777920512?ref_src=twsrc%5Etfw">2020年2月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>それに対する私のリプライ:</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="nl" dir="ltr">uint8_t *p = 1; p--; *p = v;</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1227518589403402240?ref_src=twsrc%5Etfw">2020年2月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>私はこれで話が終わると思っていたのだが、どうやらそうではなかったらしく、色々な視点からの意見が加わりながら、話は混沌を極めたのでした…。</p> <p>ということで、ここに私のこのツイートに対しての見解とか、わかったことをまとめておこうと思います。</p> <h1>私のリプライの背景について</h1> <p>uchanさんが求める「0番地にデータを書きたい」という課題設定を、私はこのように解釈しました。</p> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>において、整数0をポインタに変換すると、それはNULLポインタになる</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>において、NULLポインタへのアクセスは未定義動作である</li> <li>したがって、0番地にデータを書くことはできないのではないだろうか?</li> <li>これをすり抜ける方法はあるか?</li> </ul> <p>これを受けて、私はこのように考えました。</p> <ul> <li>NULLポインタへのアクセスが未定義となるのは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時の話である</li> <li>では<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時にNULLポインタであると<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>にバレなければ未定義動作にならないのではないだろうか?</li> <li>じゃあアドレス1を代入してポインタをつくり、それを引き算して0番地へのポインタをつくれば、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>は見逃してくれるのではないだろうか?</li> </ul> <p>そして、以下のコード片が生まれたわけです。</p> <pre class="code" data-lang="" data-unlink>uint8_t *p = 1; p--; *p = v;</pre> <p>ここで、vは何らかのuint8_t型の書き込みたいデータである(と文脈からわかると期待)。</p> <h2>仕様上の問題</h2> <p>しかしその後、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CD%AD%BC%B1%BC%D4">有識者</a>の人々がにわかにざわつき始めた。そして、私の提示したコードはやはり動かないということをherumiさんがありがたくも指摘してくださったわけです。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://t.co/37AzusUhoc">https://t.co/37AzusUhoc</a><br>Cの規格(6.3.2.3 3)では整数定数0か(void*)0がヌルポインタ(NULL)。NULLへのアクセスは未定義。したがって0へのアクセスは不可能。それ以外の整数からポインタへのキャストは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%E8%CD%FD%B7%CF%B0%CD%C2%B8">処理系依存</a>。<br>このコードはNULLへのアクセスと等価とみなして<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>やclangはud2を生成するようです。</p>&mdash; herumi (@herumi) <a href="https://twitter.com/herumi/status/1228468154596093952?ref_src=twsrc%5Etfw">2020年2月14日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>では仕様上、単なる0番地への代入コードや、私の書いたコードがなぜうまく動かないのかをみていきましょう。</p> <h3>0をポインタにキャストするとそれはnull pointerになる (6.3.2.3 - 3)</h3> <p>この仕様によれば、整数定数0となるような定数式をポインタにキャストすると、それはnull pointerになる。 そして、null pointerは、いかなるオブジェクトや関数へのポインタとも等しくならないことが保証されている。</p> <h3>null pointerを用いた間接参照は未定義動作になる (6.5.3.2 - 4)</h3> <p>この仕様によれば、<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を用いた間接参照をするときに、その参照が「無効なもの」であるとき、<code>*</code><a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の挙動は未定義となる。 ここでいう「無効なもの」には、null pointerも含まれると注釈102に書かれている。</p> <hr /> <p>したがって、0番地に1を書き込もうとして <code>*(uint8_t *)0 = 1;</code> と書いてもこれは未定義動作になる これは、整数定数0をポインタにキャストしたもの<code>(uint8_t *)0</code>がnull pointerであり(ここまでは定義された動作)、これへの間接参照が「null pointerを用いた間接参照」になるためである。</p> <p>この、null pointerへの間接参照を回避するための方法として私が編み出したのが<code>uint8_t *p = 1; p--; *p = v;</code>であるが、これも以下の仕様によって「処理系定義」の動作になる。</p> <h3>整数からポインタへの変換は処理系定義である (6.3.2.3 - 5)</h3> <p>この仕様によれば、整数からポインタへの変換を行ってもよいが、その結果は処理系定義になるという。 つまり、たとえアドレス1を表現しようとして<code>(uint8_t *)1</code>と書いても、その内部表現が整数1と等しくなるとは保証されないということである。</p> <hr /> <p>したがって、<code>uint8_t *p = 1; p--; *p = v;</code>と書いても、最初の<code>uint8_t *p = 1;</code>の段階でpがどこを指しているかは処理系の動作に完全に依存し、1番地を指しているとは限らないため、私の提案した方法は残念ながら処理系定義の結果になる。</p> <p>しかも、最適化によって、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>は<code>*p=v;</code>のタイミングでpがnull pointerになることを推測してしまう場合があるらしく、そうするとこれは未定義動作になってしまう。(これがherumiさんにご指摘いただいた部分。)</p> <p>まじか、最適化の結果未定義動作を踏むこともあるのか、つらいな…。</p> <h2>じゃあどうすればいいのか</h2> <p>これは多くの人がすでに指摘している通りで、かつ私も同意する結果なのですが、</p> <p>「処理系定義の動作に依存することなくメモリの0番地に<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>から読み書きをすることは不可能である」</p> <p>が答えです。</p> <p>これは、そもそも<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>には「メモリの何番地」に該当する概念がなく、ポインタへの整数値の代入も処理系定義であることが原因であるため、どうしようもありません。</p> <h2>なんとかできないの?</h2> <p>いくつかの点に目をつぶれば、まあ結果的に実現することは可能です。</p> <h3><code>*(uint8_t *)(0) = 1;</code> とその派生</h3> <p>これは、今まで説明してきた理由によれば未定義動作となるため、<a href="https://groups.google.com/forum/#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J">鼻から悪魔が出てきてもおかしくありません</a>。早速Compiler <a class="keyword" href="http://d.hatena.ne.jp/keyword/Explorer">Explorer</a>でやってみましょう。</p> <table> <thead> <tr> <th> </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> 9.2 </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> clang 9.0.0 </th> </tr> </thead> <tbody> <tr> <td> <code>*(uint8_t *)(0) = 1;</code> with <code>-O0</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>*(uint8_t *)(0) = 1;</code> with <code>-O3</code> </td> <td> NG(ud2) </td> <td> NG(ud2) </td> </tr> </tbody> </table> <p>残念ながら悪魔は出てきませんでしたが、最適化を有効にするとやはりud2ですね。しかし、最適化を無効にすれば一応期待通りのコードが得られます。</p> <p>と、ここで気になるWarningがclangから出力されていることに気付きました。</p> <pre class="code" data-lang="" data-unlink> &lt;source&gt;:3:5: warning: indirection of non-volatile null pointer will be deleted, not trap [-Wnull-dereference] *(uint8_t *)(0) = 1; ^~~~~~~~~~~~~~~ &lt;source&gt;:3:5: note: consider using __builtin_trap() or qualifying pointer with &#39;volatile&#39; 1 warning generated. Compiler returned: 0</pre> <p>ほう?volatileをつけると何か変わるんですかね。やってみましょう。</p> <table> <thead> <tr> <th> </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> 9.2 </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> clang 9.0.0 </th> </tr> </thead> <tbody> <tr> <td> <code>*(uint8_t * volatile)(0) = 1;</code> with <code>-O0</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>*(uint8_t * volatile)(0) = 1;</code> with <code>-O3</code> </td> <td> NG(ud2) </td> <td> NG(ud2) </td> </tr> </tbody> </table> <p>あれ、volatiileをつける場所、こっちじゃないの?</p> <table> <thead> <tr> <th> </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> 9.2 </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> clang 9.0.0 </th> </tr> </thead> <tbody> <tr> <td> <code>*(volatile uint8_t *)(0) = 1;</code> with <code>-O0</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>*(volatile uint8_t *)(0) = 1;</code> with <code>-O3</code> </td> <td> NG(ud2) </td> <td> OK </td> </tr> </tbody> </table> <p>なるほど、こうすれば、clangでは最適化を有効にしていても、volatile 修飾をすることで有効なコードを吐いてくれるようです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>は規<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B3%CA%C4%CC">格通</a>りだめみたいですが…。</p> <h3><code>uint8_t *p = 1; p--; *p = 1;</code> とその派生</h3> <p>この手法は、null pointer dereference が未定義動作になる挙動を回避した(つもりだった)ものです。(もちろん、この挙動は整数からポインタへの変換という処理系定義の動作に依存しています。)</p> <table> <thead> <tr> <th> </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> 9.2 </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> clang 9.0.0 </th> </tr> </thead> <tbody> <tr> <td> <code>uint8_t *p = 1; p--; *p = 1;</code> with <code>-O0</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>uint8_t *p = 1; p--; *p = 1;</code> with <code>-O3</code> </td> <td> NG(ud2) </td> <td> NG(ud2) </td> </tr> </tbody> </table> <p>しかし、最適化によって前半の結果pがnull pointerになることが推測されてしまっており、その結果ud2が生成されていますね。ということで、最適化を無効にするためにvolatile をつけてあげましょう。</p> <table> <thead> <tr> <th> </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> 9.2 </th> <th> <a class="keyword" href="http://d.hatena.ne.jp/keyword/x86-64">x86-64</a> clang 9.0.0 </th> </tr> </thead> <tbody> <tr> <td> <code>uint8_t * volatile p = 1; p--; *p = 1;</code> with <code>-O0</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>uint8_t * volatile p = 1; p--; *p = 1;</code> with <code>-O3</code> </td> <td> OK </td> <td> OK </td> </tr> <tr> <td> <code>volatile uint8_t * p = 1; p--; *p = 1;</code> with <code>-O3</code> </td> <td> NG(ud2) </td> <td> OK </td> </tr> </tbody> </table> <p>おー、確かに動きはしますね。でもポインタ演算が入ってしまいますが…。</p> <p>volatile修飾をポインタ変数ではなく、その指す値につけてみると、ポインタ演算に関する最適化は両者とも走るようになり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>では想定通りud2になったんですが、なんとclangでは最適化された結果である0番地への代入<code>mov byte ptr [0], 1</code> が生成されました。 clangはvolatileがついてたらnull pointerのdereferenceも許容してくれるってことみたいですね。</p> <h2>追記: <code>-fno-delete-null-pointer-checks</code> というフラグを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時につける</h2> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">-fno-delete-null-pointer-checksだと<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>/clangともに*(char*)0 = 0;で期待する(?)コードがでました。dereferenceしてるのでその先のポインタはNULLじゃないとみなす? 本来int a = p-&gt;v; if(!p)...の後ろのチェックを省略するやつ(デフォルトon)なので意味的に逆な感じもするのですが。<a href="https://twitter.com/hikalium?ref_src=twsrc%5Etfw">@hikalium</a></p>&mdash; herumi (@herumi) <a href="https://twitter.com/herumi/status/1228562292704333825?ref_src=twsrc%5Etfw">2020年2月15日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>clangと<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>の両方で期待通り動くようです。<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>のドキュメントにおける記載は<a href="https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fdelete-null-pointer-checks">ここ</a>にあります。なるほどud2になる挙動は、「絶対に引っかかることが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時にわかっている(実行時に行われる可能性がある)null pointer checkを、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>時にud2に置き換える」という最適化によるものなんですね。</p> <p>ところで調べていたら、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>オプションが追加された<a href="https://reviews.llvm.org/D47894">Clangへのパッチ</a>を見つけました。曰く:</p> <blockquote><p>Support for this option is needed for building <a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a> kernel. This is a very frequently requested feature by kernel developers.</p> <p>More details : <a href="https://lkml.org/lkml/2018/4/4/601">https://lkml.org/lkml/2018/4/4/601</a></p></blockquote> <p>なるほど、やはり<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a> Kernel開発者からの熱い要望があったんですね。(lkmlのリンクに飛ぶと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linus">Linus</a>の熱い言葉が見れるのでおすすめです。)入ったのが比較的最近(2018年中頃)というのも面白いですね。</p> <p>(Thanks @herumi, @kazuho !)</p> <h2>追記: <code>__attribute__((address_space(1)))</code> をポインタ変数につける(<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>/clang限定)</h2> <p><a href="http://blog.hatena.ne.jp/uenoku/">id:uenoku</a> さんのコメント曰く:</p> <blockquote><p><a href="http://blog.hatena.ne.jp/uenoku/">id:uenoku</a></p> <p>既出でしたら申し訳ないですが、clangなら<a class="keyword" href="http://d.hatena.ne.jp/keyword/llvm">llvm</a>::NullPointerIsDefinedをtrueにすることを考えれば良いので以下のようなコードがかけます <a href="https://godbolt.org/z/x5cXf4">https://godbolt.org/z/x5cXf4</a></p></blockquote> <p><a href="https://godbolt.org/z/x5cXf4">Compiler Explorerでの結果</a> のうち、f1, f2は前述した<code>-fno-delete-null-pointer-checks</code>によるもの、f3がこの手法です。</p> <p><code>address_space(n)</code> というattributeは、そのポインタがどの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%EC%A5%B9%B6%F5%B4%D6">アドレス空間</a>のものかを指定するもので、デフォルトは<code>address_space(0)</code>になっています。そしてこのAddress Spaceの値が、null pointerへの参照が定義された動作かを判定する<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>の関数<code>bool llvm::NullPointerIsDefined(const Function *F, unsigned AS)</code> @ <a href="https://github.com/llvm/llvm-project/blob/531c1161b9758aa7eae1a4dd8ecf11fdf4417b29/llvm/lib/IR/Function.cpp#L1628">lib/IR/Function.cpp</a> に渡されます。この関数の実装を見てみると:</p> <pre class="code" data-lang="" data-unlink>bool Function::nullPointerIsDefined() const { return getFnAttribute(&#34;null-pointer-is-valid&#34;) .getValueAsString() .equals(&#34;true&#34;); } bool llvm::NullPointerIsDefined(const Function *F, unsigned AS) { if (F &amp;&amp; F-&gt;nullPointerIsDefined()) return true; if (AS != 0) return true; return false; }</pre> <p>AS(address space)が0以外のとき、常にtrueを返すことがわかります。これで、null pointerへの参照が未定義動作ではないよと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>に教えることができるわけです。なるほどー。</p> <p>(Thanks <a href="http://blog.hatena.ne.jp/uenoku/">id:uenoku</a> !)</p> <h1>まとめ</h1> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>はやはり難しい</li> <li>こんな記事を書いて時間をつぶしている場合ではなかった</li> <li>でも仕様書を読むのも楽しいのでおすすめ</li> </ul> <h1>参考文献</h1> <ul> <li>(n1570.pdf)</li> </ul> hikalium 2019年概観 hatenablog://entry/26006613491417704 2019-12-31T19:11:58+09:00 2019-12-31T19:11:58+09:00 2019年を時系列に振り返る。Twitter埋め込みが大量にあるので注意。 1月 さくらインターネットで委託研究員としてNVDIMMたちと戯れていた(4月まで) というわけで今日からしばらくの間、さくらインターネット東京支社で、機材を使わせていただくなどの支援を受けつつ、私の興味分野の研究開発をやっていきます。みなさまよろしくおねがいします! pic.twitter.com/BJgsIMggBX— hikalium (@hikalium) 2019年1月7日 liumOS本格始動 UEFIでファイルが読めるようになったので、テストがてらロゴ画像を表示した。#liumOS pic.twitter… <p>2019年を時系列に振り返る。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Twitter">Twitter</a>埋め込みが大量にあるので注意。</p> <ul> <li>1月 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>で委託研究員としてNVDIMMたちと戯れていた(4月まで) <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">というわけで今日<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%AB%A4%E9%A4%B7">からし</a>ばらくの間、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%B5%A4%AF%A4%E9%A5%A4%A5%F3%A5%BF%A1%BC%A5%CD%A5%C3%A5%C8">さくらインターネット</a>東京支社で、機材を使わせていただくなどの支援を受けつつ、私の興味分野の研究開発をやっていきます。<br>みなさまよろしくおねがいします! <a href="https://t.co/BJgsIMggBX">pic.twitter.com/BJgsIMggBX</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1082286523796447232?ref_src=twsrc%5Etfw">2019年1月7日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>liumOS本格始動 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/UEFI">UEFI</a>でファイルが読めるようになったので、テストがてらロゴ画像を表示した。<a href="https://twitter.com/hashtag/liumOS?src=hash&amp;ref_src=twsrc%5Etfw">#liumOS</a> <a href="https://t.co/L5UBqikeAA">pic.twitter.com/L5UBqikeAA</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1085473871220723712?ref_src=twsrc%5Etfw">2019年1月16日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/VR">VR</a>環境が整備された <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「これが何だか、知らないのかい?」<br>(頷く。)<br>「最新式のNaviだよ、それもフル装備の!これだけのマシンパワーがあったら、ワイヤードに入っても全然ストレスなく自由に動けるんだろうなぁ!…俺も、自作マシンやってんだけどさ、全然かなわないや!」<br>「そんなこと…ない。」 <a href="https://t.co/X1HAViR9tZ">pic.twitter.com/X1HAViR9tZ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1086280682320478210?ref_src=twsrc%5Etfw">2019年1月18日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>試される大地に行った <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">試される大地に着いた…。 <a href="https://t.co/p3LaT87xeT">pic.twitter.com/p3LaT87xeT</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1090755859381010432?ref_src=twsrc%5Etfw">2019年1月30日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>2月 <ul> <li>VRChatに降り立った <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず最初からモデルつくるのは大変そうなので、まずはVRoidStudioのモデルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/VRM">VRM</a> Converter for VRChatで変換してやってみた。これなしで変換しようとしたらうまくいかなくてつらかったのでとても感謝しています! &gt; <a href="https://twitter.com/esperecyan?ref_src=twsrc%5Etfw">@esperecyan</a><a href="https://t.co/30R9Yy1heA">https://t.co/30R9Yy1heA</a> <a href="https://t.co/VA1vR4WICM">pic.twitter.com/VA1vR4WICM</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1092005714006966272?ref_src=twsrc%5Etfw">2019年2月3日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>ドロイド会議にスタッフ参加した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日明日は <a href="https://twitter.com/hashtag/DroidKaigi?src=hash&amp;ref_src=twsrc%5Etfw">#DroidKaigi</a> でスイッチと戯れていますのでよろしくですー! <a href="https://t.co/Pll6LLNM3C">pic.twitter.com/Pll6LLNM3C</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1093395095842254850?ref_src=twsrc%5Etfw">2019年2月7日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>OSC2019 Tokyo/Spring <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今日はOSCの504号室にいたり、あたりをふらふらしていますのでよろしくお願いしますー! <a href="https://t.co/WBEiLi6BUV">pic.twitter.com/WBEiLi6BUV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1099154033657303041?ref_src=twsrc%5Etfw">2019年2月23日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>3月 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%C3%A5%AF%A5%D1%A5%C3%A5%C9">クックパッド</a>自作キーボード会に参加した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">なんかできた図<a href="https://twitter.com/hashtag/cookpad_spring_intern?src=hash&amp;ref_src=twsrc%5Etfw">#cookpad_spring_intern</a> <a href="https://t.co/DiJ85zjQpj">pic.twitter.com/DiJ85zjQpj</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1107885693559177216?ref_src=twsrc%5Etfw">2019年3月19日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>卒業してないけど卒業式に行った</li> </ul> </li> </ul> <hr /> <ul> <li>4月 <ul> <li><p>技術書典6でOSGirls(1)を出した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">OSGirls, う35で販売します!<br>画像は売り子をしてくれる <a href="https://twitter.com/00_?ref_src=twsrc%5Etfw">@00_</a> です!<br>かんたん後払い、Pixiv pay対応なので小銭がない場合はそちらも使っていただけると!!<br>よろしくお願いします!!!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> 6 <a href="https://t.co/DqpRbK5tie">pic.twitter.com/DqpRbK5tie</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117246238515052544?ref_src=twsrc%5Etfw">2019年4月14日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2019%2F04%2F14%2F223734" title="技術書典6に初出展したところ300部の新刊が完売した話 - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2019/04/14/223734">hikalium.hatenablog.jp</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.booth.pm%2Fitems%2F1317230" title="OSGirls(電子版) - hikalium - BOOTH" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.booth.pm/items/1317230">hikalium.booth.pm</a></cite></p></li> <li><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CB%A5%B3%A5%CB%A5%B3%C4%B6%B2%F1%B5%C4">ニコニコ超会議</a>にスタッフ参加した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">無事に平成最後の超会議が終わった。<br>…帰ったら<a class="keyword" href="http://d.hatena.ne.jp/keyword/GCJ">GCJ</a>に出なければ。 <a href="https://t.co/3KlzMWznVr">pic.twitter.com/3KlzMWznVr</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1122452241703587841?ref_src=twsrc%5Etfw">2019年4月28日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p></li> </ul> </li> </ul> <hr /> <ul> <li>5月 <ul> <li>プラサミ+自作OS<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%E2%A4%AF%A4%E2%A4%AF%B2%F1">もくもく会</a> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自作OS<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%E2%A4%AF%A4%E2%A4%AF%B2%F1">もくもく会</a>ついた!<br>(プラサミと同会場)<br><br>バルって部屋の奥のエリアで自作OSもくもく勢はやっているので、ステッカー欲しい人などはこの濃い緑色のセキュキャンの名札とロゴで私を見つけてください!(随時適当に回ります) <a href="https://t.co/bKa3ZDCkMn">pic.twitter.com/bKa3ZDCkMn</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1127433705180393473?ref_src=twsrc%5Etfw">2019年5月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>6月 <ul> <li>某社の面接を受けた</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%AB%A1%BC">ハッカー</a>ズチャンプルー登壇 @ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%CE%B0%B5%E5%C2%E7%B3%D8">琉球大学</a> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%AB%A1%BC">ハッカー</a>ズチャンプルー2019 <a href="https://twitter.com/hashtag/hcmpl?src=hash&amp;ref_src=twsrc%5Etfw">#hcmpl</a><br>とても楽しかった!<br>他の皆さんの発表もとても面白かったし、何より私の発表を楽しんでくださった方がたくさんいてよかったです。(正直、レイヤ違いではと直前まで不安でしたが、いい意味で裏切られました。)<br>運営、そして参加者の皆さん、ありがとうございました! <a href="https://t.co/oVgGJUXJ8Y">pic.twitter.com/oVgGJUXJ8Y</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1144988596744540160?ref_src=twsrc%5Etfw">2019年6月29日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.google.com%2Fpresentation%2Fd%2F1mbLk70RKi-ExLzb78WosCu5DujpQN2K7B9iSbUGRXq4%2Fedit%23slide%3Did.p" title="現代のコンピュータにおける自作OS事情" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://docs.google.com/presentation/d/1mbLk70RKi-ExLzb78WosCu5DujpQN2K7B9iSbUGRXq4/edit#slide=id.p">docs.google.com</a></cite></li> </ul> </li> </ul> <hr /> <ul> <li>7月 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AB%A1%BC%A5%CD%A5%EB">カーネル</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/VM">VM</a>勉強会に参加</li> <li>研究室のゼミ合宿に参加</li> </ul> </li> </ul> <hr /> <ul> <li>8月 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%EF%A5%F3%A5%B4">ドワンゴ</a>でバイトを開始した(継続中)</li> <li>某社からオファーをもらったので承諾</li> <li>セキュキャンでRuiさんとともにC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミの講師を担当 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">セキュキャンDay0(準備日)にhikaliumがロードされました。<a href="https://twitter.com/hashtag/seccamp?src=hash&amp;ref_src=twsrc%5Etfw">#seccamp</a> <a href="https://t.co/abBxbJsaZ7">pic.twitter.com/abBxbJsaZ7</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1160767515322007552?ref_src=twsrc%5Etfw">2019年8月12日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>ラボユースキャンプに卒業生として参加 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ラボユース合宿から帰還。めっちゃ進捗が出て、1000行近いコード追加の結果、<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>上のliumOSがUSBキーボードに一応対応しました!実機にももう少しで対応できるはず…!<a href="https://twitter.com/hashtag/liumOS?src=hash&amp;ref_src=twsrc%5Etfw">#liumOS</a> <a href="https://t.co/J9s8OmUZ4A">pic.twitter.com/J9s8OmUZ4A</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1166634989569462272?ref_src=twsrc%5Etfw">2019年8月28日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>9月 <ul> <li>iOSDC Japan 2019 スタッフ参加 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">1000超えないなあ…。<br>みなさんもっと本気出してください!デ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をもっとたくさん <a href="https://twitter.com/hashtag/iOSDC?src=hash&amp;ref_src=twsrc%5Etfw">#iOSDC</a> Japan 2019 の<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSID">SSID</a>に繋いでください!お願いします! <a href="https://t.co/4wVIj4FPFe">pic.twitter.com/4wVIj4FPFe</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1170216220571754496?ref_src=twsrc%5Etfw">2019年9月7日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>成田空港で難民化からのNY旅行 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%B9%A5%C8%A5%D4%A5%A2">ディストピア</a>特有の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%B8%A5%BF%A5%EB%A5%B5%A5%A4%A5%CD%A1%BC%A5%B8">デジタルサイネージ</a>による配給通達です。 <a href="https://t.co/Wu1XA0zsFV">pic.twitter.com/Wu1XA0zsFV</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1171079336994017280?ref_src=twsrc%5Etfw">2019年9月9日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ニュー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%E8%A1%BC%A5%AF%B8%F8">ヨーク公</a>立図書館の裏の、夜でも昼のように明るい公園の図です。 <a href="https://t.co/pi0UnPf6OT">pic.twitter.com/pi0UnPf6OT</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1172702424005525504?ref_src=twsrc%5Etfw">2019年9月14日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> <li>技術書典7でOSGirls2を出した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">設営完了です!<br>く51D (2Fの奥の方)で会いましょう!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a><a href="https://twitter.com/hashtag/OS_Girls?src=hash&amp;ref_src=twsrc%5Etfw">#OS_Girls</a> <a href="https://t.co/PIpfIm5nEs">pic.twitter.com/PIpfIm5nEs</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1175591129728708608?ref_src=twsrc%5Etfw">2019年9月22日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.booth.pm%2Fitems%2F1574662" title="OSGirls2(製本版) - hikalium - BOOTH" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.booth.pm/items/1574662">hikalium.booth.pm</a></cite></li> </ul> </li> </ul> <hr /> <ul> <li>10月 <ul> <li>CODEBLUE2019スタッフ参加 <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今年もCODEBLUEで<a class="keyword" href="http://d.hatena.ne.jp/keyword/NOC">NOC</a>をしています。楽しんでいこうー! <a href="https://t.co/f0ob0MyZm0">pic.twitter.com/f0ob0MyZm0</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1188623834192023552?ref_src=twsrc%5Etfw">2019年10月28日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>11月 <ul> <li>SANS Netwarsに参加</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Serial%20Experiments%20Lain">Serial Experiments Lain</a>のファンイベント クラブサイベリアに参加した <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%AF%A5%BB%A5%E9">アクセラ</a>(ノンアルコール)をキメてる <a href="https://twitter.com/hashtag/%E3%82%AF%E3%83%A9%E3%83%96%E3%82%B5%E3%82%A4%E3%83%99%E3%83%AA%E3%82%A2?src=hash&amp;ref_src=twsrc%5Etfw">#クラブサイベリア</a> <a href="https://t.co/6I4dtwsBBH">pic.twitter.com/6I4dtwsBBH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1195627552255004672?ref_src=twsrc%5Etfw">2019年11月16日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></li> </ul> </li> </ul> <hr /> <ul> <li>12月 <ul> <li>SECCON 2019 国際決勝にHarekazeの一員として行った <blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SECCON国際決勝にHarekaze出撃します〜! <a href="https://t.co/qczRJDb2mz">pic.twitter.com/qczRJDb2mz</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1208184312979324929?ref_src=twsrc%5Etfw">2019年12月21日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2019%2F12%2F22%2F232138" title="SECCON CTF 2019 Final competition Q4 &quot;box&quot; write-up - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2019/12/22/232138">hikalium.hatenablog.jp</a></cite></li> </ul> </li> </ul> <h1>まとめ</h1> <p>今年もなんだかんだ活発に活動していた。本当にえらい!</p> <p>タスクを積みすぎるところは反省点なので、来年はある程度自制することも覚えましょう。(すでに積み上がったタスクを眺めながら。)</p> <p>来年もよい年になりますように。</p> hikalium SECCON CTF 2019 Final competition Q4 "box" write-up hatenablog://entry/26006613487857358 2019-12-22T23:21:38+09:00 2019-12-22T23:21:38+09:00 2019-12-22に開催されたSECCONの国際決勝に、hiww, h_noson, st98ともにHarekazeとして参加しました。(昨年は国内決勝に参加してました。) お疲れ様でした。11位でした pic.twitter.com/lfESEQxZ3L— h_noson (@h_noson) 2019年12月22日 順位はあまり振るわず、14チーム中11位でしたが、個人的には問題4の"box"のattackフラグを全部回収できたので大満足です。ということで、問題4の私なりの解き方についてまとめておきます。 "box"問題概要 今回は6つ大問がありましたが、そのうちの4問目でした。問題とし… <p>2019-12-22に開催されたSECCONの国際決勝に、<a href="https://twitter.com/hiww">hiww</a>, <a href="https://twitter.com/h_noson">h_noson</a>, <a href="https://twitter.com/st98_">st98</a>ともに<a href="https://harekaze.com/">Harekaze</a>として参加しました。(<a href="https://hikalium.hatenablog.jp/entry/2018/12/24/002411">昨年</a>は国内決勝に参加してました。)</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">お疲れ様でした。11位でした <a href="https://t.co/lfESEQxZ3L">pic.twitter.com/lfESEQxZ3L</a></p>&mdash; h_noson (@h_noson) <a href="https://twitter.com/h_noson/status/1208647619473362944?ref_src=twsrc%5Etfw">2019年12月22日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>順位はあまり振るわず、14チーム中11位でしたが、個人的には問題4の"box"のattackフラグを全部回収できたので大満足です。ということで、問題4の私なりの解き方についてまとめておきます。</p> <h2>"box"問題概要</h2> <p>今回は6つ大問がありましたが、そのうちの4問目でした。問題としては、stripされた<a class="keyword" href="http://d.hatena.ne.jp/keyword/x86">x86</a>バイナリと、それに特定の入力を与えた際の分岐トレース結果が配布されるので、同一の分岐トレースが得られるような入力をみつける、というものです。</p> <p>……あれ?この話前にも聞いたことがありますね。そうです、今年の予選では、完全に同様の形式の問題(follow-me)が出されていたのでした。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2019%2F10%2F20%2F154511" title="SECCON 2019 Online CTF Writeup - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2019/10/20/154511">hikalium.hatenablog.jp</a></cite></p> <p>ということで、あとはやるだけです。</p> <p>Attackフラグとしては、box1から4と名付けられた4つの問題がダウンロードできるので、それを解いて入力を<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>に投げるとフラグが得られます。</p> <p>Defenceフラグとしては、box1に類似した問題が1時間ごとに出され、それをその時間内に解いて<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>に投げるとチームのtokenを設置できるのですが、ちょっと厳しかったので諦めました(後述)。</p> <p>では、box1から4まで順に見ていきましょう。</p> <h2>box1</h2> <h3>入力形式の特定</h3> <p>とりあえず普通の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>バイナリなので実行してみます。</p> <pre class="code" data-lang="" data-unlink>$ ./box usage: ./box formula</pre> <p>なるほど…式を引数で渡すんですね。</p> <pre class="code" data-lang="" data-unlink>$ ./box &#39;1+3&#39; error: unhandled char &#39;+&#39;</pre> <p>うーん、だめですね。じゃああれかな、予選の時と同じ入力形式なのかな?</p> <pre class="code" data-lang="" data-unlink>./box &#39;1,3,+&#39; error: unhandled char &#39;,&#39;</pre> <p>違うみたい…。(ここから試行錯誤することしばらく。)</p> <pre class="code" data-lang="" data-unlink>$ ./box &#39;&#39; error: stack is empty $ ./box &#39;0&#39; error: stack is empty $ ./box &#39;00&#39; error: stack is empty $ ./box &#39;000&#39; error: stack is empty $ ./box &#39;0000&#39; 0</pre> <p>あー…なるほど?(さらにしばらく試行錯誤して。)</p> <pre class="code" data-lang="" data-unlink>$ ./box &#39;00010002a&#39; 3 $ ./box &#39;00010002b&#39; -1 $ ./box &#39;00010002c&#39; 2 $ ./box &#39;00010002d&#39; 1 $ ./box &#39;00010002e&#39; 2 $ ./box &#39;00010002f&#39; 5 $ ./box &#39;00010002g&#39; error: unhandled char &#39;g&#39;</pre> <p>なるほど、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>はa-fなんですね。(なぜ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>を読まないのか(つかれてたので))。</p> <h3>トレースをみてみる</h3> <pre class="code" data-lang="" data-unlink>$ cat box.trace [ {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;***/box1&#34;, &#34;image_id&#34;: 1, &#34;base_addr&#34;: &#34;0x557a93890000&#34;, &#34;image_size&#34;: &#34;0x135f&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib64/ld-linux-x86-64.so.2&#34;, &#34;image_id&#34;: 2, &#34;base_addr&#34;: &#34;0x7fb95ac8c000&#34;, &#34;image_size&#34;: &#34;0x26c23&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;[vdso]&#34;, &#34;image_id&#34;: 3, &#34;base_addr&#34;: &#34;0x7ffc905a6000&#34;, &#34;image_size&#34;: &#34;0x100a&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib/x86_64-linux-gnu/libc.so.6&#34;, &#34;image_id&#34;: 4, &#34;base_addr&#34;: &#34;0x7fb9464a4000&#34;, &#34;image_size&#34;: &#34;0x3f0adf&#34;}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a9389064e&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a93890ed4&#34;, &#34;branch_taken&#34;: false}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a938907f5&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a93890786&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a93890ef4&#34;, &#34;branch_taken&#34;: false}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a938906b0&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a93890690&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a93890e3f&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x557a938906c0&#34;, &#34;branch_taken&#34;: true}, ... ]</pre> <p>こんな感じで<a class="keyword" href="http://d.hatena.ne.jp/keyword/JSON">JSON</a>が書かれています。 base_addrは最初の要素に書いてあるので、ちゃんとやるなら引き算をすれば、適当にするなら下4桁をとればファイル内のアドレスになりそうです。 というわけで、objdumpと照らし合わせればすべてわかりそう…でもせっかくトレーサーのソースも与えられているし、あとのことも考えるとトレーサーの環境を用意した方がよくない?という気持ちになったので用意することに。</p> <h3>トレーサーの環境構築</h3> <p>問題で配布されているファイルの中には、トレース出力を得るために使ったトレーサーのソースも含まれていました。なので、これを実行したいのですが、これは<a href="https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool">Intel Pin</a>というライブラリに依存しているので、適当にPinの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を落としてきてビルドします。そして、Pinを用いたサンプルコードの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リに行って、サンプルのうちひとつをコピーし、それのソースと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>を書き換えて、トレーサーのライブラリファイルをビルドしました。</p> <pre class="code" data-lang="" data-unlink>/path/to/pin/source/tools/branchtrace $ ls branchtrace.cpp branchtrace.out debugtrace.cpp makefile makefile.rules obj-intel64 /path/to/pin/source/tools/branchtrace $ ls obj-intel64/ branchtrace.o branchtrace.so</pre> <p>この<code>branchtrace.so</code>というのがトレーサーになります。</p> <h3>トレーサーの実行</h3> <p><code>branchtrace.so</code>を直接実行することはできないので、pinを介して呼び出します。以下のような感じで。</p> <pre class="code" data-lang="" data-unlink>q4/box1$ /path/to/pin/pin -t /path/to/pin/source/tools/branchtrace/obj-intel64/branchtrace.so -- ./box &#39;00010002a&#39; 3 q4/box1$ cat branchtrace.out | head -n 7 [ {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/vagrant/seccon2019df/q4/box1/box&#34;, &#34;image_id&#34;: 1, &#34;base_addr&#34;: &#34;0x55aa08e61000&#34;, &#34;image_size&#34;: &#34;0x135f&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib64/ld-linux-x86-64.so.2&#34;, &#34;image_id&#34;: 2, &#34;base_addr&#34;: &#34;0x7f4f2c012000&#34;, &#34;image_size&#34;: &#34;0x26c23&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;[vdso]&#34;, &#34;image_id&#34;: 3, &#34;base_addr&#34;: &#34;0x7fff31bb3000&#34;, &#34;image_size&#34;: &#34;0x100a&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib/x86_64-linux-gnu/libc.so.6&#34;, &#34;image_id&#34;: 4, &#34;base_addr&#34;: &#34;0x7f4f1782a000&#34;, &#34;image_size&#34;: &#34;0x3f0adf&#34;}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x55aa08e6164e&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x55aa08e61ed4&#34;, &#34;branch_taken&#34;: false},</pre> <p>できましたね!</p> <h3>結果を整形する</h3> <p>pinの出力してくれるtrace結果はまあまあ綺麗なのですが、各分岐のアドレスがイメージ内の相対ではないので、配布されたものと手元では値が異なり比較が面倒です。 ということで、ささっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を書いて整形してくれるようにしましょう。私はNodejsが好きな変人なのでnodejsで書いた<code>print.js</code>がこちら。</p> <pre class="code" data-lang="" data-unlink>const fs = require(&#39;fs&#39;); const filename = process.argv[2]; const parseTrace = (fileName) =&gt; { const trace = JSON.parse(fs.readFileSync(fileName, &#39;utf-8&#39;)); const base_addr = parseInt(trace[0].base_addr, 16); const branches = trace.filter(e =&gt; (e.inst_addr != undefined)).map(e =&gt; { if (e.event === &#39;call&#39;) { return { &#39;addr&#39;: (parseInt(e.inst_addr, 16) - base_addr).toString(16), &#39;target&#39;: (parseInt(e.target_addr, 16) - base_addr).toString(16) }; } return { &#39;addr&#39;: (parseInt(e.inst_addr, 16) - base_addr).toString(16), &#39;taken&#39;: e.branch_taken }; }); return branches; } const print = (branches) =&gt; { for (var i = 0; i &lt; branches.length;) { const b = branches[i]; var count = 0; while (i &lt; branches.length &amp;&amp; branches[i].addr == b.addr &amp;&amp; branches[i].taken == b.taken) { count++; i++; } console.log(`${JSON.stringify(b)} * ${count}`); } console.log(branches.length); } const branches = parseTrace(filename); print(branches);</pre> <p>最初のほうでは気づかなかったのですが、同じ分岐をぐるぐる回る際もけっこうあって、それを <code>*N</code>と表示した方がわかりやすかったので、そうしていたりします。(色々適当に工夫しながらできあがった完成形。) また、あとのほうでjmp ccだけでなくcallも出てきたので、それにも一応対応してます。</p> <p>実行するとこんな感じです。</p> <pre class="code" data-lang="" data-unlink>q4/box1$ node print.js box.trace | head -n 5 {&#34;addr&#34;:&#34;64e&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;ed4&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;7f5&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;786&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;ef4&#34;,&#34;taken&#34;:false} * 1</pre> <p>よいよい、みやすくなった。</p> <h3>入力と分岐の対応関係を調べる</h3> <p>本当ならファジングなり、静的解析でツールを使うなり、ちゃんとやったほうが早いと思うのですが、私はobjdumpしかわからないので、バイナリのobjdumpを横においておきながら、入力と分岐を変化させて、トレーサーをぶん回しながら、どういう挙動をしているのか調べます。</p> <p>メモの断片:</p> <pre class="code" data-lang="" data-unlink>XXXXYYYYa {&#34;addr&#34;:&#34;ddc&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bac&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;bb6&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;a21&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;a31&#34;,&#34;taken&#34;:true},* Y+1 times {&#34;addr&#34;:&#34;9c4&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bf5&#34;,&#34;taken&#34;:true}, 00020001b {&#34;addr&#34;:&#34;ddc&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bac&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;bb6&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bfe&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;9c4&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;c3d&#34;,&#34;taken&#34;:true}, 00200010c {&#34;addr&#34;:&#34;ddc&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bac&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;bb6&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;bfe&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;c46&#34;,&#34;taken&#34;:false}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;964&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;a5c&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;a82&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;a94&#34;,&#34;taken&#34;:true}, // opR + 1 {&#34;addr&#34;:&#34;9c4&#34;,&#34;taken&#34;:true}, {&#34;addr&#34;:&#34;c85&#34;,&#34;taken&#34;:true}, </pre> <p>なるほど、結局のところ</p> <pre class="code" data-lang="" data-unlink>XXXXYYYYa -&gt; XXXX+YYYY XXXXYYYYb -&gt; XXXX-YYYY XXXXYYYYc -&gt; XXXX*YYYY XXXXYYYYd -&gt; min(XXXX, YYYY) XXXXYYYYe-&gt; max(XXXX, YYYY)</pre> <p>という感じの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%D5%A5%DD%A1%BC%A5%E9%A5%F3%A5%C9%B5%AD%CB%A1">逆ポーランド記法</a>電卓なんですねー(X, Yは数字) あと、addとmulでは、右辺の値に対応して、途中の分岐の呼ばれる数が変わるんですねーということがわかりました。</p> <p>ということで、適当に合いそうな入力を考えて、トレース……よし、合っていそう。では、投げましょう。私はこんな入力をえらびました。</p> <pre class="code" data-lang="" data-unlink>001000000012ce0010a0000b</pre> <p>わーい!次にいきましょうー</p> <h2>box2</h2> <p>なんだ楽勝じゃん、次もどうせ入力が違うだけなのでは?と思ったのですが</p> <pre class="code" data-lang="" data-unlink>$ ./box usage: ./box input</pre> <p>どうも入力はformura、つまり式ではないようです。色々入れてみましょう。</p> <pre class="code" data-lang="" data-unlink>$ ./box hoge _t $ ./box hogehoge #^L8 $ ./box hogehogehoge ɿAV $ ./box hogehogehogefuga @%Zyr $ ./box hogehogehogefugassssssssssssssssssssssssss -2&#34;qC $ ./box hogehogehogefugasssssssssssssssssssssssssssssssssssssss N?sG&gt;*AA^8&gt;PwvƴP $ ./box hogehogehogefugassssssssssssssssssssssssssssssssssssssssssss z:R Rc-OgGOx</pre> <p>おお?なんか印字<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C9%D4%C7%BD">不能</a>な文字を出してくるときもありますね。それに、入力と出力の対応も不明です。困った。 とりあえずobjdump...と。</p> <pre class="code" data-lang="" data-unlink> 8c9: c6 45 e0 27 movb $0x27,-0x20(%rbp) 8cd: c6 45 e1 51 movb $0x51,-0x1f(%rbp) 8d1: c6 45 e2 90 movb $0x90,-0x1e(%rbp) 8d5: c6 45 e3 79 movb $0x79,-0x1d(%rbp) 8d9: c6 45 e4 66 movb $0x66,-0x1c(%rbp) 8dd: c6 45 e5 b7 movb $0xb7,-0x1b(%rbp) 8e1: c6 45 e6 25 movb $0x25,-0x1a(%rbp) 8e5: c6 45 e7 61 movb $0x61,-0x19(%rbp) 8e9: c6 45 e8 45 movb $0x45,-0x18(%rbp) 8ed: c6 45 e9 63 movb $0x63,-0x17(%rbp) 8f1: c6 45 ea c3 movb $0xc3,-0x16(%rbp) 8f5: c6 45 eb f8 movb $0xf8,-0x15(%rbp) 8f9: c6 45 ec f4 movb $0xf4,-0x14(%rbp) 8fd: c6 45 ed 96 movb $0x96,-0x13(%rbp) 901: c6 45 ee a5 movb $0xa5,-0x12(%rbp) 905: c6 45 ef 2e movb $0x2e,-0x11(%rbp) 909: 48 8b 85 00 ff ff ff mov -0x100(%rbp),%rax 910: 48 8b 40 08 mov 0x8(%rax),%rax 914: 48 89 85 18 ff ff ff mov %rax,-0xe8(%rbp) 91b: 48 8b 85 18 ff ff ff mov -0xe8(%rbp),%rax 922: 48 89 c7 mov %rax,%rdi 925: e8 86 fd ff ff callq 6b0 &lt;strlen@plt&gt;</pre> <p>なんか16回movしてそのあとstrlenしている…16という数字があやしいな?</p> <p>と思いながらトレースをしていたところ、以下の事実を発見した。</p> <pre class="code" data-lang="" data-unlink>$ node trace.js ./box &#39;0&#39; | tail -n 1 821 $ node trace.js ./box &#39;0123&#39; | tail -n 1 821 $ node trace.js ./box &#39;0123456789abcdef&#39; | tail -n 1 821 $ node trace.js ./box &#39;0123456789abcdefg&#39; | tail -n 1 1535 $ node trace.js ./box &#39;0123456789abcdefghi&#39; | tail -n 1 1535 $ node trace.js ./box &#39;0123456789abcdef0123456789abcdef&#39; | tail -n 1 1535 $ node trace.js ./box &#39;0123456789abcdef0123456789abcdef0&#39; | tail -n 1 2249</pre> <p>ここでtrace.jsは、私が適当に書いたトレーサーをラップする<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>で、最後にトレースの総分岐数が出てくるのですが、なぜか入力が16文字増えるごとに段階的に分岐数が増える。しかも、トレース結果をみると、同じ分岐回数なら、分岐の内容は一切変わっていない。</p> <p>16文字の境界を超えるごとに、分岐数は<code>1535-821 == 2249 - 1535 == 714</code>増えるから、つまるところ<code>16*N+1</code>以上<code>16*N+16</code>文字<code>(N &gt;=0)</code>の入力を与えた時、その総分岐数は<code>821+N*714</code>になるというわけです。</p> <p>さて、与えられたtraceの総分岐数は8675であったから、この式で逆算すると<code>(8675-821)/714 =&gt; 11</code>となるわけです。おお、まじか、ぴったり整数じゃん!(ここで嬉しい気分になる。)</p> <p>というわけで、気軽に<code>16*11+16 =&gt; 192</code>文字のファイルを生成して送りつけました。わーい!</p> <h2>box3</h2> <p>box2がさくっと終わったので、どんどんやっていこうーとなった流れで到達したbox3は、めっちゃ楽しかった。だって</p> <pre class="code" data-lang="" data-unlink>$ ./box usage: ./box filename</pre> <p>と出たので、適当にtouchしたファイルを食べさせたら</p> <pre class="code" data-lang="" data-unlink>./box empty.txt [!] Not implemented: code=0 EAX = 00000000 ECX = 00000000 EDX = 00000000 EBX = 00000000 ESP = 00007c00 EBP = 00007c00 ESI = 00000000 EDI = 00000000 EIP = 00007c00</pre> <p>見慣れた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>名が出てきたんですもの。しかも、0x7c00!!!!!(この嬉しさを理解したい方は30日でできるOS自作入門か<a class="keyword" href="http://d.hatena.ne.jp/keyword/Intel">Intel</a> SDMでも読んでおいてください。)</p> <p>これは十中八九<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF%A1%BC">エミュレーター</a>だろう、と思ったので、早速NOPを食べさせると</p> <pre class="code" data-lang="" data-unlink>$ echo &#39;90&#39; | xxd -r -p &gt; nop.bin $ ./box nop.bin [!] Not implemented: code=0 EAX = 00000000 ECX = 00000000 EDX = 00000000 EBX = 00000000 ESP = 00007c00 EBP = 00007c00 ESI = 00000000 EDI = 00000000 EIP = 00007c01</pre> <p>たしかにさっきより1バイト進んでから死んでますね。やったね!</p> <h3>どんな命令が実装されているのか特定する</h3> <p>そうきたら、あとはこの子の実装状況と動作のようすを解明してあげるだけです。 最初は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Intel">Intel</a> SDM Vol.2のopcode表をみて適当にあたりをつけていたのですが、あまりにもきつかったので方針転換しました。</p> <p>幸運にもNOPが実装されていることはわかったので、NOPの数を変えてトレースしてみましょう。</p> <p>トレース結果は長いのですが、着目すべき点はただ一つ: call命令のトレース結果だけです。私のprint.jsでは、call命令の場合はtargetというメンバを記録するようにしているので、それで<a class="keyword" href="http://d.hatena.ne.jp/keyword/grep">grep</a>をかけます。</p> <pre class="code" data-lang="" data-unlink>$ echo &#39;90&#39; | xxd -r -p &gt; nop1.bin $ echo &#39;90 90&#39; | xxd -r -p &gt; nop2.bin $ node trace.js ./box nop1.bin | grep target {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2e44&#34;} * 1 $ node trace.js ./box nop2.bin | grep target {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2e44&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2e44&#34;} * 1</pre> <p>なるほど…つまるところ、+0x2e44のところがNOPの命令を処理しているようですね。</p> <p>どうしてcall命令にのみ着目すればいいのかというと、たいていのCPU<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF">エミュレータ</a>は、動作を高速にするために、入力された命令のバイトを配列の添字として、関数ポインタの配列にアクセスして各処理を呼び出すからです。(作ってみるとわかるこの気持ち。)</p> <p>というわけで、call命令のtargetを見れば、どの命令が実行されているのかわかりそうですね。</p> <p>では、求めるべきトレース結果から、どの命令が使われているか抽出してみましょう。とりあえずcall命令だけを抜き出してみると、</p> <pre class="code" data-lang="" data-unlink>$ node print.js box.trace | grep target {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2ebd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2ebd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;1ead&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2389&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;317d&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;1ead&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2389&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;317d&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;1ead&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2389&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;317d&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;1ead&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2389&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;317d&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;1ead&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2389&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;317d&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;2159&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;28fd&#34;} * 1 {&#34;addr&#34;:&#34;3b2d&#34;,&#34;target&#34;:&#34;3269&#34;} * 1</pre> <p>おー、やはりindirectなcall命令は1箇所しかないんですね。で、このtargetの一意なリストは以下です。</p> <pre class="code" data-lang="" data-unlink>$ node print.js box.trace | grep target | cut -d \&#34; -f 8 | sort | uniq 1ead 2159 2389 28fd 2ebd 317d 3269</pre> <p>さて、ここからどうやって命令オペコードを知ればよいでしょうか。</p> <p>さきほど言ったように、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%DF%A5%E5%A5%EC%A1%BC%A5%BF">エミュレータ</a>は命令オペコードをテーブルの添字にすることで関数ポインタを得て、それをcallしているはずです。 では、そのテーブルはどこにあるのか…objdumpをみるとあやしいところを見つけました。</p> <pre class="code" data-lang="" data-unlink> 340b: 55 push %rbp 340c: 48 89 e5 mov %rsp,%rbp 340f: 48 83 ec 10 sub $0x10,%rsp 3413: ba 00 08 00 00 mov $0x800,%edx 3418: be 00 00 00 00 mov $0x0,%esi 341d: 48 8d 3d 7c 2c 20 00 lea 0x202c7c(%rip),%rdi # 2060a0 &lt;__cxa_finalize@plt+0x2055f0&gt; 3424: e8 f7 d5 ff ff callq a20 &lt;memset@plt&gt; 3429: 48 8d 05 7d ea ff ff lea -0x1583(%rip),%rax # 1ead &lt;__cxa_finalize@plt+0x13fd&gt; 3430: 48 89 05 71 2c 20 00 mov %rax,0x202c71(%rip) # 2060a8 &lt;__cxa_finalize@plt+0x2055f8&gt; 3437: 48 8d 05 0c eb ff ff lea -0x14f4(%rip),%rax # 1f4a &lt;__cxa_finalize@plt+0x149a&gt; 343e: 48 89 05 7b 2c 20 00 mov %rax,0x202c7b(%rip) # 2060c0 &lt;__cxa_finalize@plt+0x205610&gt; 3445: 48 8d 05 02 ec ff ff lea -0x13fe(%rip),%rax # 204e &lt;__cxa_finalize@plt+0x159e&gt; 344c: 48 89 05 c5 2c 20 00 mov %rax,0x202cc5(%rip) # 206118 &lt;__cxa_finalize@plt+0x205668&gt; 3453: 48 8d 05 62 ec ff ff lea -0x139e(%rip),%rax # 20bc &lt;__cxa_finalize@plt+0x160c&gt; 345a: 48 89 05 87 2d 20 00 mov %rax,0x202d87(%rip) # 2061e8 &lt;__cxa_finalize@plt+0x205738&gt; 3461: 48 8d 05 f1 ec ff ff lea -0x130f(%rip),%rax # 2159 &lt;__cxa_finalize@plt+0x16a9&gt; 3468: 48 89 05 f9 2d 20 00 mov %rax,0x202df9(%rip) # 206268 &lt;__cxa_finalize@plt+0x2057b8&gt; 346f: 48 8d 05 8b ed ff ff lea -0x1275(%rip),%rax # 2201 &lt;__cxa_finalize@plt+0x1751&gt; 3476: 48 89 05 fb 2d 20 00 mov %rax,0x202dfb(%rip) # 206278 &lt;__cxa_finalize@plt+0x2057c8&gt; 347d: 48 8d 05 25 ee ff ff lea -0x11db(%rip),%rax # 22a9 &lt;__cxa_finalize@plt+0x17f9&gt; 3484: 48 89 05 f5 2d 20 00 mov %rax,0x202df5(%rip) # 206280 &lt;__cxa_finalize@plt+0x2057d0&gt; 348b: 48 8d 05 89 ee ff ff lea -0x1177(%rip),%rax # 231b &lt;__cxa_finalize@plt+0x186b&gt; 3492: 48 89 05 ef 2d 20 00 mov %rax,0x202def(%rip) # 206288 &lt;__cxa_finalize@plt+0x2057d8&gt; 3499: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) </pre> <p>何やらばんばんleaして代入してますね。しかも、関数のアドレスっぽいです。もう少し下の方をみると</p> <pre class="code" data-lang="" data-unlink> 3677: 48 8d 05 c6 f7 ff ff lea -0x83a(%rip),%rax # 2e44 &lt;__cxa_finalize@plt+0x2394&gt; 367e: 48 89 05 9b 2e 20 00 mov %rax,0x202e9b(%rip) # 206520 &lt;__cxa_finalize@plt+0x205a70&gt;</pre> <p>NOP命令だとわかっている、0x2e44の関数ポインタを代入しているところをみつけました! どうもこのテーブルの先頭は、ソースの流れ的に</p> <pre class="code" data-lang="" data-unlink> 341d: 48 8d 3d 7c 2c 20 00 lea 0x202c7c(%rip),%rdi # 2060a0 &lt;__cxa_finalize@plt+0x2055f0&gt;</pre> <p>曰く0x2060a0のようです。では、この予想が正しいか調べてみましょう。</p> <ul> <li>NOPのオペコードは0x90</li> <li>NOPの関数ポインタはオフセット0x206520に格納されている</li> <li>ポインタの大きさは8bytes</li> <li>関数ポインタのテーブルは0x2060a0から始まっている?</li> </ul> <p>関数ポインタのテーブルをop_tableとしたとき、</p> <pre class="code" data-lang="" data-unlink>op_table[0x90] == &lt;+0x2e44のアドレス&gt;</pre> <p>になっていてほしいわけです。これはつまり</p> <pre class="code" data-lang="" data-unlink>*(op_table + 8 * 0x90) == &lt;+0x2e44のアドレス&gt;</pre> <p>というのと等価ですから、格納されるべきアドレスは、テーブルの先頭op_tableから8 * 0x90 == 1152離れているはずです。op_tableを0x2060a0とすれば、その結果は…</p> <pre class="code" data-lang="" data-unlink>0x2060a0 + 8 * 0x90 =&gt; 0x206520</pre> <p>ビンゴ!NOPの関数ポインタが代入されているアドレスと一致しますね!!</p> <p>というわけで、これでテーブルを生成するコードで各関数がテーブルのどのオフセットに格納されているか調べれば、対応するオペコードがわかりそうです。</p> <p>…とりあえず、テーブル内の各オフセットと対応するオペコードは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>でさくっと生成しました。</p> <pre class="code" data-lang="" data-unlink>[ [ &#39;2060a8&#39;, &#39;1&#39; ], [ &#39;2060c0&#39;, &#39;4&#39; ], [ &#39;206118&#39;, &#39;f&#39; ], [ &#39;2061e8&#39;, &#39;29&#39; ], [ &#39;206268&#39;, &#39;39&#39; ], [ &#39;206278&#39;, &#39;3b&#39; ], [ &#39;206280&#39;, &#39;3c&#39; ], [ &#39;206288&#39;, &#39;3d&#39; ], [ &#39;2063e0&#39;, &#39;68&#39; ], [ &#39;2063f0&#39;, &#39;6a&#39; ], [ &#39;206420&#39;, &#39;70&#39; ], [ &#39;206428&#39;, &#39;71&#39; ], [ &#39;206430&#39;, &#39;72&#39; ], [ &#39;206438&#39;, &#39;73&#39; ], [ &#39;206440&#39;, &#39;74&#39; ], [ &#39;206448&#39;, &#39;75&#39; ], [ &#39;206460&#39;, &#39;78&#39; ], [ &#39;206468&#39;, &#39;79&#39; ], [ &#39;206480&#39;, &#39;7c&#39; ], [ &#39;206490&#39;, &#39;7e&#39; ], [ &#39;206498&#39;, &#39;7f&#39; ], [ &#39;2064b8&#39;, &#39;83&#39; ], [ &#39;2064e0&#39;, &#39;88&#39; ], [ &#39;2064e8&#39;, &#39;89&#39; ], [ &#39;2064f0&#39;, &#39;8a&#39; ], [ &#39;2064f8&#39;, &#39;8b&#39; ], [ &#39;206508&#39;, &#39;8d&#39; ], [ &#39;206520&#39;, &#39;90&#39; ], [ &#39;2066b8&#39;, &#39;c3&#39; ], [ &#39;2066d8&#39;, &#39;c7&#39; ], [ &#39;2066e8&#39;, &#39;c9&#39; ], [ &#39;206708&#39;, &#39;cd&#39; ], [ &#39;2067c0&#39;, &#39;e4&#39; ], [ &#39;2067e0&#39;, &#39;e8&#39; ], [ &#39;2067e8&#39;, &#39;e9&#39; ], [ &#39;2067f8&#39;, &#39;eb&#39; ], [ &#39;206800&#39;, &#39;ec&#39; ], [ &#39;206810&#39;, &#39;ee&#39; ], [ &#39;206840&#39;, &#39;f4&#39; ], [ &#39;206898&#39;, &#39;ff&#39; ] ]</pre> <p>そして、あとはobjdumpの結果と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Intel">Intel</a> SDM Vol.2をじーっと見つめると…</p> <pre class="code" data-lang="" data-unlink>1ead -&gt; 2060a8 -&gt; 0x01 -&gt; ADD Ev,Gv 2159 -&gt; 206268 -&gt; 0x39 -&gt; CMP Ev,Gv 2389 -&gt; INC r32 28fd -&gt; 206498 -&gt; 0x7f -&gt; JNLE / JG 2ebd -&gt; -&gt; mov r32, imm32 317d -&gt; 2067f8 -&gt; 0xeb -&gt; short Jb 3269 -&gt; 206840 -&gt; 0xf4 -&gt; HLT</pre> <p>はい!</p> <p>incとmovに関しては、オペコード内に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%B3%A1%BC%A5%C7%A5%A3%A5%F3%A5%B0">エンコーディング</a>されている(つまり、複数のオペコードが同じ操作を表現する)ので、バイナリ中でもループを回して代入されていました。なのでちょっと歯抜けです。(INCとかがオフセットいくつで実装されているかを調べたりして突き止めた。)</p> <p>さて、あとはprint.jsを拡張して、トレース結果からオペコードを表示してみるか…となったんですが</p> <pre class="code" data-lang="" data-unlink>PROLOGUE mov r32, imm32 mov r32, imm32 CMP Ev,Gv {&#34;addr&#34;:&#34;bdf&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;be6&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;a20&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;c7d&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;cbf&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;cd6&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;d0e&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;13a1&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;13bc&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1cb5&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;1cca&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1cf1&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1d2d&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;1d41&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1e86&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1d67&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;21f8&#34;,&#34;taken&#34;:true} * 1 JNLE / JG ADD Ev,Gv INC r32 ... INC r32 short Jb CMP Ev,Gv {&#34;addr&#34;:&#34;bdf&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;be6&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;a20&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;c7d&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;cbf&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;cd6&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;d0e&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;13a1&#34;,&#34;taken&#34;:false} * 1 {&#34;addr&#34;:&#34;13bc&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1cb5&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1cf1&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1d2d&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1e86&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;1d67&#34;,&#34;taken&#34;:true} * 1 {&#34;addr&#34;:&#34;21f8&#34;,&#34;taken&#34;:true} * 1 JNLE / JG JNLE / JG taken HLT-&gt;END 444</pre> <p>これはCMP Ev, Gvの分岐列だけベタで、あとは命令の名前で表示してみたんですが、なぜか微妙に長さが違います。考えられるのは…演算結果によって分岐が変わるということです。 CMP命令は、引き算の結果に合わせてフラグ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>を設定しますから、いかにもありそうなかんじです。また、分岐命令についても分岐列の長さが1命令程度変動する時があり、これは分岐が行われたか否かを示しているようでした。 というわけで、うまくつじつまを合わせるとこんな感じの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>列をバイナリにして食べさせてあげたトレース結果を投げると(長い)フラグが降ってきました。うれしいね!</p> <pre class="code" data-lang="" data-unlink>.intel_syntax noprefix mov eax, 1 mov ebx, 5 cmp eax, ebx jg out add ecx, edx inc eax jmp a a: cmp edx, ebx jg out # false add ecx, edx inc eax jmp b b: cmp edx, ebx jg out # false add ecx, edx inc eax jmp d d: cmp edx, ebx jg out # false add ecx, edx inc eax jmp e e: cmp eax, ebx jg cccc cccc: add ecx, edx inc eax jmp g g: cmp ebx, edx jg out # true add ecx, edx inc eax jmp f f: out: hlt</pre> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>とバイナリの抽出は以下のような感じで。(out.binがおいしいバイナリです。)</p> <pre class="code" data-lang="" data-unlink>gcc -m16 -c -o test.o test.S &amp;&amp; objcopy -O binary test.o out.bin</pre> <p>さあ、次もいきましょう!!</p> <h2>box4</h2> <p>さて、次は何かな、と思ったら</p> <pre class="code" data-lang="" data-unlink>$ md5sum box3/box box4/box d8614ad07b9efbb87a6049bd7b5da1c7 box3/box d8614ad07b9efbb87a6049bd7b5da1c7 box4/box</pre> <p>同じバイナリじゃないですか!やったね、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>が流用できるよ!</p> <h3>追加の命令列を特定</h3> <pre class="code" data-lang="" data-unlink>2c33 -&gt; 2064e8 -&gt; 0x89 -&gt; MOV Ev,Gv 23e7 -&gt;          -&gt; DEC r32 24c3 -&gt; -&gt; POP r32 251a -&gt; 2063e0 -&gt; 0x68 -&gt; PUSH lz 2645 -&gt; 206440 -&gt; 0x74 -&gt; JZ/JE 2695 -&gt; 206448 -&gt; 0x75 -&gt; JNZ/JNE 3144 -&gt; 2067e8 -&gt; 0xe9 -&gt; JMP near Jz</pre> <p>かんたんだね!</p> <h3>print.jsを拡張</h3> <ul> <li>分岐のtaken/not taken</li> <li>OF(オーバーフローフラグ)の表示を追加</li> </ul> <p><script src="https://gist.github.com/c084c706be79938d0c26beb7c2864e3b.js"> </script></p> <p><a href="https://gist.github.com/c084c706be79938d0c26beb7c2864e3b">Parser for SECCON 2019 final q4 box4</a></p> <p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を、与えられたトレース結果に適用すると、こんなかんじの出力が得られます。</p> <pre class="code" data-lang="" data-unlink>$ node print.js box.trace PROLOGUE PUSH imm32 PUSH imm32 PUSH imm32 PUSH imm32 POP r32 POP r32 DEC r32 ZF=false OF=false MOV r/m32,r32 ADD Ev,Gv DEC r32 ZF=false OF=false JNZ/JNE JNZ/JNE taken? ADD Ev,Gv DEC r32 ZF=true OF=false JNZ/JNE CMP Ev,Gv ZF=false JZ/JE JMP near Jz POP r32 DEC r32 ZF=false OF=false MOV r/m32,r32 ADD Ev,Gv DEC r32 ZF=true OF=false JNZ/JNE CMP Ev,Gv ZF=false JZ/JE JMP near Jz POP r32 DEC r32 ZF=false OF=false MOV r/m32,r32 ADD Ev,Gv DEC r32 ZF=false OF=false JNZ/JNE JNZ/JNE taken? ADD Ev,Gv DEC r32 ZF=false OF=false JNZ/JNE JNZ/JNE taken? ADD Ev,Gv DEC r32 ZF=true OF=false JNZ/JNE CMP Ev,Gv ZF=true JZ/JE JZ/JE taken HLT-&gt;END 613</pre> <p>もうほとんど<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>だね!</p> <h2>入力バイナリを錬成</h2> <p>メモ書き込みですがこんな感じでとけた。</p> <pre class="code" data-lang="" data-unlink>.intel_syntax noprefix //PUSH lz //PUSH lz //PUSH lz //PUSH lz .byte 0x68, 0x02, 0x00, 0x00, 0x00 .byte 0x68, 0x02, 0x00, 0x00, 0x00 .byte 0x68, 0x02, 0x00, 0x00, 0x00 .byte 0x68, 0x02, 0x00, 0x00, 0x00 //POP r32 //POP r32 //DEC r32 ZF=false : r32 != 1 //MOV Ev,Gv //ADD Ev,Gv //DEC r32 ZF=false : r32 != 1 //JNZ/JNE //JNZ/JNE taken? pop edx // edx = 1 pop esi // esi = 1 dec edx // op != 0 mov ecx,edx add edx,eax dec esi jne fake fake: //ADD Ev,Gv //DEC r32 ZF=true : r32 == 1 //JNZ/JNE //CMP Ev,Gv ZF=false //JZ/JE //JMP near Jz add ecx,ecx dec esi // op should be 1 jnz c c: cmp eax,ecx jz d .byte 0xe9, 0x00, 0x00, 0x00, 0x00 d: //POP r32 //DEC r32 ZF=false //MOV Ev,Gv //ADD Ev,Gv //DEC r32 ZF=true //JNZ/JNE pop ebx dec ebx mov ecx,ebx add edi,ecx dec ebx jne e e: //CMP Ev,Gv ZF=false //JZ/JE //JMP near Jz cmp eax,ecx jz p .byte 0xe9, 0x00, 0x00, 0x00, 0x00 p: //POP r32 //DEC r32 ZF=false //MOV Ev,Gv //ADD Ev,Gv //DEC r32 ZF=false //JNZ/JNE //JNZ/JNE taken pop ebx dec ebx mov ecx,ecx add edi,ecx dec edi jne q q: //ADD Ev,Gv //DEC r32 ZF=false //JNZ/JNE //JNZ/JNE taken add edi,ecx dec edi jnz m m: //ADD Ev,Gv //DEC r32 ZF=true //JNZ/JNE add ecx,ecx dec ebx jne n n: //CMP Ev,Gv ZF=true //JZ/JE //JZ/JE taken cmp eax,eax jz s s: //HLT-&gt;END hlt</pre> <h2>あれ、Defenceポイントはどうしたの?</h2> <p>box1のvariantってことだったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>とかは一緒かなと思っていたのですが、完全に変わっていたのでつらかった。自動化するにはちゃんとファジングとかデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>を活用する必要がありそうだなあという気持ちになりました。強くなりたいです。</p> <h2>他に何をやりましたか?</h2> <p>MimuraのフラッシュをダンプしてFATを読む試みをしたりした。でもうまくいかなかった。st98さんが実機を持って帰ったので朗報を期待している。</p> <p>Bad mouseをst98さんが解いてくれたのだが、実機を持っていなかったようなので、去年かどこかで配られたのを家に置いてあった私が代わりに実行しました。 マウスが動いてフラグが塗られるのは楽しかった。しかし、待ち時間が長かった…(st98さん曰く、もっとwaitを短くできたらしいのでそうするといいと思います。)</p> <p>以下、塗られたフラグの実際の画像です。</p> <p><figure class="figure-image figure-image-fotolife" title="FLAG for Bad Mouse"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20191222/20191222231359.png" alt="f:id:hikalium:20191222231359p:plain" title="f:id:hikalium:20191222231359p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>FLAG for Bad Mouse</figcaption></figure></p> <h2>まとめ</h2> <p>問題4はめっちゃ楽しかった。作問者の友利<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%E0%BD%EF">奈緒</a>さん、いい問題をありがとうございます!</p> <p>坂井さんの問題は、ちょっとやる気が出なかったです。私のバイナリ鍛錬が足りないのも要因ですが、単純にあまり問題がおもしろくなかったのと、ディフェンスポイントの入りかたにゲーム性がないなどの問題もあったと私は思います。来年はアーキの数で殴るタイプではない、面白く解けるマルチ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>問題を期待しています…。</p> <p>とはいえ、全体的には楽しめたのでよかったです。SECCONはSECCONなので!と私は思っています。</p> <p>運営のみなさま、ありがとうございました。</p> hikalium 自作OS開発におけるTips集 〜liumOSの場合〜 hatenablog://entry/26006613486286493 2019-12-19T23:14:40+09:00 2019-12-19T23:14:40+09:00 これは、自作OS Advent Calendar 2019 の7番目の素数日の記事です。(遅れてごめんなさい!) はじめに github.com liumOSは、2018年の中頃から私が一人で開発している自作OSです。これまでにいくつかの自作OSを作っては壊し続けてきましたが、今回が3作目になります。(蛇足ですが、前作はchnosという名前で、2010-2012年に主に開発していたようです。) 今回は、このliumOS自体の紹介ではなく、開発をしてゆく中で色々と工夫したポイントを紹介したいと思います。 ビルドの依存関係を自動生成する プロジェクトの規模が大きくなってくると、全ファイルを毎回ビル… <p>これは、<a href="https://adventar.org/calendars/4027">自作OS Advent Calendar 2019</a> の7番目の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>日の記事です。(遅れてごめんなさい!)</p> <h2>はじめに</h2> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhikalium%2Fliumos" title="hikalium/liumos" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/hikalium/liumos">github.com</a></cite></p> <p><a href="https://github.com/hikalium/liumos">liumOS</a>は、2018年の中頃から私が一人で開発している自作OSです。これまでにいくつかの自作OSを作っては壊し続けてきましたが、今回が3作目になります。(蛇足ですが、前作は<a href="https://github.com/chnos">chnos</a>という名前で、2010-2012年に主に開発していたようです。)</p> <p>今回は、このliumOS自体の紹介<b>ではなく</b>、開発をしてゆく中で色々と工夫したポイントを紹介したいと思います。</p> <h2>ビルドの依存関係を自動生成する</h2> <p>プロジェクトの規模が大きくなってくると、全ファイルを毎回ビルドしていては時間がかかるようになってきます。 liumOSプロジェクトでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>のソース(<code>.cc</code>)とヘッダ(<code>.h</code>)ファイルが合計80個程度あり、これらを毎回ビルドするのはCPU時間の無駄です。 そこで、分割<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>により、変更のないファイルを再度ビルドしないようにする方法がよくとられますが、ソースファイルには変更がなくても、それがincludeしているヘッダファイルに変更があった場合は、やはり再度ビルドする必要があります。そのため、各ソースファイルがどのヘッダをincludeしているのかを<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>に記述する必要があるのですが、これは人間のやるべきことではありません!ファイル一つ一つの依存関係を列挙するのは面倒ですし、依存関係が変わった際に整合性をとれる保証もありません。</p> <p>ということで、面倒なことは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>にやらせましょう。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえずClang / <a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a> のオプションで -MD -MF foo.d とかすることで<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>向けの依存関係を吐けることがわかりました。これを使えば意外と簡単に行けそう。<a href="https://t.co/WWZADaqoUL">https://t.co/WWZADaqoUL</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1159082091952271361?ref_src=twsrc%5Etfw">2019年8月7日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>詳細は<a href="https://clang.llvm.org/docs/ClangCommandLineReference.html#dependency-file-generation">clangのドキュメント</a>などをみてもらうことにして、以下ではliumOSの場合を説明します。(ソースは<a href="https://github.com/hikalium/liumos/blob/c10c4430b37572fc5b11223424d69578b37880dd/src/Makefile">こちら</a>。)</p> <p>まずは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>にこのようなルールを書いておきます。</p> <pre class="code" data-lang="" data-unlink>%.o.d : %.c Makefile @$(LLVM_CC) $(CXXFLAGS_LOADER) -MD -MF $@ -c -o $*.o $*.c &gt;/dev/null 2&gt;&amp;1 @echo &#39;DEP $@&#39; %.o.d : %.cc Makefile @$(LLVM_CXX) $(CXXFLAGS_LOADER) -MD -MF $@ -c -o $*.o $*.cc &gt;/dev/null 2&gt;&amp;1 @echo &#39;DEP $@&#39; %.o.d : %.S Makefile @touch $@ # generate dummy @echo &#39;DEP $@&#39; ...</pre> <p>ここで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>_CC/CXXはC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>へのパス、CXX_FLAGS_LOADRERは、ローダ用のCFLAGSが入っています。オブジェクトファイルを生成する各ルールのパラメータを少し変えて<code>オブジェクトファイルの名前.d</code>というファイルを生成するルールを書いています。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>ソース<code>.S</code>など、依存するヘッダがないものはダミーを生成しておきます。</p> <p>そして、さらに以下のような記述を<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>の<b>最後に</b>書いておきます。</p> <pre class="code" data-lang="" data-unlink>-include $(LOADER_DEPS) -include $(KERNEL_DEPS)</pre> <p>このLOADER_DEPSには、上で説明した生成規則で生成される<code>*.d</code>のファイルが列挙されています。(<code>acpi.o.d apic.o.d asm.o.d inthandler.o.d ...</code> のような感じです。)</p> <p>実際には、このような感じで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>のリストから生成しています。</p> <pre class="code" data-lang="" data-unlink>COMMON_SRCS= \ acpi.cc apic.cc asm.S inthandler.S \ ... LOADER_SRCS= $(COMMON_SRCS) \ efimain.cc \ ... KERNEL_SRCS= $(COMMON_SRCS) \ command.cc \ ... LOADER_OBJS= $(addsuffix .o, $(basename $(LOADER_SRCS))) LOADER_DEPS= $(addsuffix .o.d, $(basename $(LOADER_SRCS))) KERNEL_OBJS= $(addsuffix .elf.o, $(basename $(KERNEL_SRCS))) KERNEL_DEPS= $(addsuffix .elf.d, $(basename $(KERNEL_SRCS)))</pre> <p>Makeは、この<code>include</code>ディレクティブをみつけると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>のincludeと同じようにそのファイルの内容を書かれた場所に展開しようとするのですが、もしそのファイルが存在しなかった場合、これまで読み込んだ生成規則を適用して、読み込むべきファイルを生成しようとしてくれます。これにより、対象のソースファイルが更新された場合や、依存関係を記したファイルが存在しない場合は、自動的それをmakeしてくれるわけです。</p> <p>生成される<code>.d</code>ファイルの中身は、このような感じになっています。</p> <pre class="code" data-lang="" data-unlink>$ cat acpi.o.d acpi.o: acpi.cc liumos.h acpi.h apic.h generic.h \ /usr/local/Cellar/llvm/9.0.0_1/lib/clang/9.0.0/include/stddef.h \ /usr/local/Cellar/llvm/9.0.0_1/lib/clang/9.0.0/include/__stddef_max_align_t.h \ third_party_root/include/stdint.h \ third_party_root/include/machine/_default_types.h \ third_party_root/include/sys/features.h \ third_party_root/include/_newlib_version.h \ third_party_root/include/limits.h third_party_root/include/newlib.h \ third_party_root/include/sys/cdefs.h \ third_party_root/include/sys/syslimits.h \ third_party_root/include/sys/config.h \ third_party_root/include/machine/ieeefp.h \ third_party_root/include/sys/_intsup.h \ third_party_root/include/sys/_stdint.h immintrin.h loader_support.h \ guid.h asm.h console.h efi.h efi_file.h elf.h \ third_party_root/include/elf.h gdt.h githash.h hpet.h interrupt.h \ ring_buffer.h scheduler.h process.h execution_context.h \ kernel_virtual_heap_allocator.h paging.h stl.h phys_page_allocator.h \ sys_constant.h pmem.h keyboard.h keyid.h serial.h sheet.h \ sheet_painter.h text_box.h</pre> <p>ここに書かれた生成規則の依存関係をみて、Makeは実際に<code>acpi.o</code>を生成するかどうか決定してくれます。わーい、これでCPU時間を節約できましたね!</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>のどちらでもビルドしたい!</h2> <p>liumOSは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>のどちらでもビルドできるようになっています。これは主に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>ツールチェーンが異なるプラットフォーム向けのクロスビルドにデフォルトで対応してくれているおかげなのですが、ツールチェーン自体は対応していても、周辺のライブラリとの兼ね合いで困難な点がいくつかあったので、少し説明したいと思います。</p> <p>まず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>標準のclangは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Apple">Apple</a>が少し手を加えているようで、なんと<code>x86_64-pc-win32-coff</code> や<code>x86_64-unknown-none-elf</code>などのターゲット指定に対応していないという悲しい事実があります。また、liumOSではEDK2や<a class="keyword" href="http://d.hatena.ne.jp/keyword/gnu">gnu</a>-<a class="keyword" href="http://d.hatena.ne.jp/keyword/efi">efi</a>などの<a class="keyword" href="http://d.hatena.ne.jp/keyword/UEFI">UEFI</a>開発環境を用いずに、clang+lldのみでOSのローダを生成しているのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>にはなんとlldが入っていません!(その代わり、<a href="https://opensource.apple.com/source/ld64/">ld64</a>というリンカが入っているようです。)ですから、<a href="https://brew.sh/">Homebrew</a>経由でふつうの<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>ツールチェーンを入れる必要があります。</p> <p>これでツールチェーン自体は揃ったのですが、環境ごとに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>を切り替えなければなりません。そこで、liumOSでは以下の<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a>で、該当する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>向けのツールチェーン情報を取得しています。</p> <pre class="code" data-lang="" data-unlink>$ cat common.mk THIS_DIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) OSNAME=${shell uname -s} ifeq ($(OSNAME),Darwin) $(THIS_DIR)cc_cache.gen.mk : $(THIS_DIR)scripts/gen_tool_defs_linux.sh @ $(THIS_DIR)scripts/gen_tool_defs_macos.sh &gt; $@ else $(THIS_DIR)cc_cache.gen.mk : $(THIS_DIR)scripts/gen_tool_defs_linux.sh @ $(THIS_DIR)scripts/gen_tool_defs_linux.sh &gt; $@ endif include $(THIS_DIR)cc_cache.gen.mk CLANG_SYSTEM_INC_PATH=$(shell $(THIS_DIR)./scripts/get_clang_builtin_include_dir.sh $(LLVM_CXX))</pre> <p>ここで、なぜ直接シェルを叩いてツールチェーンの情報を変数に入れずに、cc_cache.gen.mkなるファイルを生成して読み込んでいるかというと、</p> <pre class="code" data-lang="" data-unlink>$ cat scripts/gen_tool_defs_macos.sh LLVM_PREFIX=`brew --prefix llvm` echo &#34;LLVM_CC:=${LLVM_PREFIX}/bin/clang&#34; echo &#34;LLVM_CXX:=${LLVM_PREFIX}/bin/clang++&#34; echo &#34;LLVM_LLD_LINK:=${LLVM_PREFIX}/bin/lld-link&#34; echo &#34;LLVM_LD_LLD:=${LLVM_PREFIX}/bin/ld.lld&#34; echo &#34;LLVM_AR:=${LLVM_PREFIX}/bin/llvm-ar&#34; echo &#34;LLVM_RANLIB:=${LLVM_PREFIX}/bin/llvm-ranlib&#34;</pre> <p>この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>中の<code>brew --prefix llvm</code>がちょっと重くて、</p> <pre class="code" data-lang="" data-unlink>$ time brew --prefix llvm /usr/local/opt/llvm real 0m0.723s user 0m0.406s sys 0m0.303s</pre> <p>毎回実行するコストが大きいためです。ビルドするたびに待たされるのは困りますよね?</p> <p>というわけで、無事各ツールのパスは手に入ったわけですが、もう一つ引っ掛かりどころがあります。それは、<code>stdint.h</code>などの、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>が提供するヘッダファイルのパスについてです。</p> <p>C標準ライブラリのうち、<code>stdint.h</code>などの一部のヘッダは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>の実装に依存するため、標準ライブラリではなく<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>によって提供されます。このヘッダは通常であれば、デフォルトのインクルードパスに含まれているため、気にする必要はないのですが、私たちはOSを書きたいので、<code>-nostdlibinc</code> <code>-nostdlib</code>を設定してしまっています。そうすると、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>が提供するヘッダファイル、つまりは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>さえあれば使えるはずのヘッダファイルが見えなくなってしまい、困ってしまいます。(newlibなども、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>が提供するstdint.hに依存しているため、なんとかしないといけません。)</p> <p>では、この「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>が提供するヘッダファイル」はどこにあるのかというと…</p> <blockquote><p>the default location to look for builtin headers is in a path $(dirname /path/to/tool)/../lib/clang/3.3/include relative to the tool binary. <a href="https://clang.llvm.org/docs/LibTooling.html#libtooling-builtin-includes">https://clang.llvm.org/docs/LibTooling.html#libtooling-builtin-includes</a></p></blockquote> <p>ということで、わかりづらいのですが、ツールチェインのバイナリが置かれているパスから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%EA%C2%D0%A5%D1%A5%B9">相対パス</a>で<code>../lib/clang/&lt;clangのバージョン&gt;/include</code> にあるようです。</p> <p>…clangのバージョンがいるの、つらい…。</p> <p>ということで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%A7%A5%EB%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">シェルスクリプト</a>でよしなにやります。</p> <pre class="code" data-lang="" data-unlink>$ cat scripts/get_clang_builtin_include_dir.sh #!/bin/bash if [ &#34;$(uname)&#34; == &#39;Darwin&#39; ] || [ &#34;$(expr substr $(uname -s) 1 5)&#34; == &#39;Linux&#39; ]; then # macOS, Linux version=`$1 --version | head -1 | sed &#39;s/^.*[^0-9] \([0-9]*\.[0-9]*\.[0-9]*\).*$/\1/&#39;` basepath=&#34;$(dirname $(dirname $(which $1)))&#34; echo ${basepath}/lib/clang/${version}/include else echo &#34;Your platform ($(uname -a)) is not supported.&#34; exit 1 fi</pre> <p>ここで、第一引数にはclangへのパスが入ってきていることを想定しています(上記のcommon.mkを参照)。このような<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を、以下のように実行すれば、めでたく組み込みヘッダファイルのインクルードパスを得ることができます。</p> <pre class="code" data-lang="" data-unlink>$ ./scripts/get_clang_builtin_include_dir.sh /usr/local/opt/llvm/bin/clang /usr/local/opt/llvm/lib/clang/9.0.0/include</pre> <p>これを適宜<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>に指定してあげれば、無事に<code>stdint.h</code>などが使えるようになるはずです!</p> <p>というわけで、「ツールチェーンのパス」と「組み込みヘッダファイルのパス」に気をつければ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/macOS">macOS</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>でクロスビルドをすることはそんなに難しくありません。皆さんもぜひお試しください!</p> <h2>まとめ</h2> <p>自作OSは、一人もしくは少人数で作っている場合がほとんどだとは思いますが、その割に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>の規模が大きくなりがちです。そのような状況下で、効率よく、ストレスをためずに開発をするためには、今回紹介したような開発環境としての工夫も大事になってきます。 この記事をきっかけに、みなさんの自作OS開発が少しでも効率化・汎用化されれば幸いです。 年末、そして来年も、自作OSを楽しんでいきましょう!</p> hikalium SECCON 2019 Online CTF Writeup hatenablog://entry/26006613452642288 2019-10-20T15:45:11+09:00 2019-10-20T15:45:11+09:00 follow-me Harekazeの一員として参加しました。4724点を得て14位だったようです。 私は2問に取り組み、うち1問を解けたのでメモ。 follow-me (reversing) ちょっとした計算機アプリのバイナリが渡される。そのプログラムをIntel Pin を利用したトレーサでトレースした結果と、そのトレーサのソースが与えられる。このトレース結果が同一になるような、アプリケーションへの入力を求めてねという問題。 与えられているトレース結果はこんな感じ。 {"event": "image_load", "image_name": "/home/tomori/follow-me/… <p><figure class="figure-image figure-image-fotolife" title="follow-me"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20191020/20191020154255.png" alt="f:id:hikalium:20191020154255p:plain" title="f:id:hikalium:20191020154255p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>follow-me</figcaption></figure></p> <p><a href="https://harekaze.com/">Harekaze</a>の一員として参加しました。4724点を得て14位だったようです。</p> <p>私は2問に取り組み、うち1問を解けたのでメモ。</p> <h2>follow-me (reversing)</h2> <p>ちょっとした計算機アプリのバイナリが渡される。そのプログラムを<a href="https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool">Intel Pin</a> を利用したトレーサでトレースした結果と、そのトレーサのソースが与えられる。このトレース結果が同一になるような、アプリケーションへの入力を求めてねという問題。</p> <p>与えられているトレース結果はこんな感じ。</p> <pre class="code" data-lang="" data-unlink>{&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/home/tomori/follow-me/build/sample/calc&#34;, &#34;image_id&#34;: 1, &#34;base_addr&#34;: &#34;0x55f6b4d44000&#34;, &#34;image_size&#34;: &#34;0x1377&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib64/ld-linux-x86-64.so.2&#34;, &#34;image_id&#34;: 2, &#34;base_addr&#34;: &#34;0x7f13ae220000&#34;, &#34;image_size&#34;: &#34;0x26c23&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;[vdso]&#34;, &#34;image_id&#34;: 3, &#34;base_addr&#34;: &#34;0x7ffc2b775000&#34;, &#34;image_size&#34;: &#34;0x100a&#34;}, {&#34;event&#34;: &#34;image_load&#34;, &#34;image_name&#34;: &#34;/lib/x86_64-linux-gnu/libc.so.6&#34;, &#34;image_id&#34;: 4, &#34;base_addr&#34;: &#34;0x7f1399a39000&#34;, &#34;image_size&#34;: &#34;0x3f0adf&#34;}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x55f6b4d445de&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x55f6b4d44f44&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: false}, {&#34;event&#34;: &#34;branch&#34;, &#34;inst_addr&#34;: &#34;0x55f6b4d44765&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true},</pre> <p>最初の行の<code>base_addr</code>と、各分岐結果の<code>inst_addr</code>を差し引きすることで、実行バイナリ内のオフセットがわかる。</p> <p>h_noson師匠が数秒で入力の文法と分岐の解析結果を与えてくれたので、あとは入力結果を推測するだけという簡単なお仕事。</p> <pre class="code" data-lang="" data-unlink>0-9 (c): val = c - 0x30 + val * 10 ,: push val to stack +: pop twice and push(x + y) -: pop twice and push(x - y) *: pop twice and push(x * y) m: pop twice and push(min(x, y)) M: pop twice and push(max(x, y)) C: pop twice and push(x C y)</pre> <p>たとえば<code>./calc '5,3,+'</code>の結果は<code>8</code>になる。そんなかんじ。 数値は複数桁になることもできて、先頭が0埋めでも問題ないことを確認した。</p> <pre class="code" data-lang="" data-unlink>0xc1c (false): 0-9 0xbe9 (false): , 0xc58 (false): + 0xcaf (false): - 0xd06 (false): * 0xd5d (false): m 0xdb4 (false): M 0xe08 (false): C</pre> <p>また、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>による分岐だけでなく、計算時の値によっても分岐結果が変わることがわかった。</p> <p>乗算は、左辺の値-1回、0xa1fを通る。</p> <pre class="code" data-lang="" data-unlink>r &#39;13,3,*&#39; -&gt; 0xa1fは12回呼ばれる</pre> <p>加算は、(右辺の値%10) + 1回、0xa1fを通る。</p> <pre class="code" data-lang="" data-unlink>r &#39;13,18,+&#39; -&gt; 0xa1fは9回</pre> <p>そして、0xe87の分岐がtrueのときに項を読み続けるので、これを境界としてトレース結果を分割し、上記の結果を総合して推測すればよい。</p> <p>たとえば、以下のようなトレース列は</p> <pre class="code" data-lang="" data-unlink>e87&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, be9&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, c1c&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, c58&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, caf&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, d06&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: false}, 8dc&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, 8dc&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a5b&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a81&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a0b&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, a1f&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: false}, a81&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: false}, 93e&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true}, d54&#34;, &#34;next_inst_addr&#34;: &#34;0&#34;, &#34;branch_taken&#34;: true},</pre> <ul> <li>0xd06の分岐がfalseなので乗算</li> <li>0xa1fの分岐を7回通っているので、この演算が実行される際の左辺の値は8</li> </ul> <p>ということがわかる。</p> <p>トレース結果より、入力列は</p> <p><code> ccc,ccc,ccc,ccc,ccc,cccc,ccc,mm-mM-ccc,ccc,ccc,mm-ccc,ccc,ccc,ccc,ccc,-+-M+ccc,ccc,ccc,mm* </code></p> <p>と予想できる(cは数字が入る)。これは実際に値が1つに収束するのでよさそうである。</p> <p>加算と乗算に気をつけつつ、後ろ側からいい感じに値を割り当てていく。たとえばこんなかんじに。</p> <p><code> 001,002,003,004,005,0006,007,mm-mM-001,002,003,mm-008,005,001,004,001,-+-M+001,002,003,mm* </code></p> <p>あとは問題の指示通りにサーバーに答えを投げてあげれば、フラグを得ることができた。</p> <p><code> {"error":false,"flag":"SECCON{Is it easy for you to recovery input from execution trace? Keep hacking:)}","message":"Thanks! I'll give you a flag as a thank you."} </code></p> <h2>repair (forensics)</h2> <p>解けなかった…。</p> <p>問題としては、壊れたAVIファイルが与えられ、その先頭1セクタ(512Bytes)が欠損しているので、なんとかしてその部分(つまりはヘッダ)を復元してねーという話だった。</p> <p>解析プログラムをささっと書いて、だいたいどんなデータ構造か、フレーム数はいくつかなどを調べて、それっぽいパラメータで<a class="keyword" href="http://d.hatena.ne.jp/keyword/ffmpeg">ffmpeg</a>で動画を生成し、先頭512Bytesをつぎはぎするなどしたが、codecが特定できず断念した。</p> <p><script src="https://gist.github.com/7567d487d32af63ec0f4bc68e5a354cb.js"> </script></p> <p><a href="https://gist.github.com/7567d487d32af63ec0f4bc68e5a354cb">AVI file reader for SECCON 2019 Online CTF</a></p> <p>moviリスト内の00dcというチャンクがフレームのデータで、こんな感じで並んでいる。</p> <pre class="code" data-lang="" data-unlink>@+0x00146E: LIST size = 2789052 movi @+0x00147A: 00dc size = 32440 00 00 7E B8 03 C0 02 1C 00 01 10 00 7E AE 00 00 00 00 02 1C 03 C0 20 00 00 04 22 00 00 0A 00 00 00 00 00 00 32 00 7E 94... @+0x00933A: 00dc size = 4086 01 00 0F F6 03 C0 02 1C 00 01 11 00 0F EC 00 00 00 00 02 1C 03 C0 20 00 00 04 22 00 00 04 31 00 0F D8 00 00 00 00 00 00... @+0x00A338: 00dc size = 4086 01 00 0F F6 03 C0 02 1C 00 01 11 00 0F EC 00 00 00 00 02 1C 03 C0 20 00 00 04 22 00 00 04 31 00 0F D8 00 00 00 00 00 00...</pre> <p>各フレームデータの先頭8bytesは以下のようなフォーマットになっているっぽい</p> <pre class="code" data-lang="" data-unlink> 00 00 7E B8 03 C0 02 1C ^^ 0ならキーフレーム, 1なら中間フレーム ^^ ^^ ビッグエンディアンでこのフレーム全体のサイズ(00dcのサイズと一緒) ^^ ^^ 960(Width) ^^ ^^ 540(Height)</pre> <p>ということがわかったので、ビッグ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A8%A5%F3%A5%C7%A5%A3%A5%A2%A5%F3">エンディアン</a>でこういうフォーマットになっているcodecないかなと探したり、<a class="keyword" href="http://d.hatena.ne.jp/keyword/ffmpeg">ffmpeg</a>のcodecを片端から試してこのような出力が得られないか試したが間に合わなかった。かなしい。</p> <p>参考文献: <a href="http://www.morgan-multimedia.com/download/odmlff2.pdf">OpenDML AVI File Format Extensions</a></p> <h2>まとめ</h2> <p>CTFは生活リズムを破壊する(たのしいので)</p> <p>あとAVIファイルのフレームデータの区切りがHex上で見えるようになったのでよかった。</p> hikalium 技術書典6に初出展したところ300部の新刊が完売した話 hatenablog://entry/17680117127027667656 2019-04-14T22:37:34+09:00 2019-04-14T22:37:34+09:00 2019-04-14, 技術書典6が池袋で開催されました。私は、前回の技術書典5の際に、買いに行く側としての初参加を果たしたのですが、その際「来年は書く側で出しなよ〜」と多数の皆様に煽られ応援されたのでした。 来年は技術書展に出す側に回りたいですねえ…?(皆様にとても煽られた)— hikalium (@hikalium) October 8, 2018 その流れを踏まえ、今回は絶対に書いてやるぞ!という強い意志で、アンケートをとった結果 技術書展6、私が以下のいずれかを書くとして、最も読みたいのは…— hikalium (@hikalium) January 11, 2019 OS Girls… <p>2019-04-14, 技術書典6が池袋で開催されました。私は、前回の技術書典5の際に、買いに行く側としての初参加を果たしたのですが、その際「来年は書く側で出しなよ〜」と多数の皆様に<del>煽られ</del>応援されたのでした。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xe02f850)"><p lang="ja" dir="ltr">来年は技術書展に出す側に回りたいですねえ…?(皆様にとても煽られた)</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1049213075809755137?ref_src=twsrc%5Etfw">October 8, 2018</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>その流れを踏まえ、今回は絶対に書いてやるぞ!という強い意志で、アンケートをとった結果</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0x2ed7758)"><p lang="ja" dir="ltr">技術書展6、私が以下のいずれかを書くとして、最も読みたいのは…</p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1083691745097875456?ref_src=twsrc%5Etfw">January 11, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p><code>OS Girls</code>というタイトルが人々にもっとも望まれているということでしたので、ひとまずサークル参加の応募をしたところ、高倍率の中ではありましたが、運良く参加できることが決まったのでした。</p> <p>もうこうなったら、何か出さないわけにはいかない(出せなかった場合、もう一生技術書典からbanされてもおかしくない)ので、とにかくやっていくぞという気持ちになれました。</p> <p>結果、初めての執筆・入稿・販売ということで、ヒヤヒヤしながらではありましたが、なんとなんと用意していた印刷部数のすべて、300部を頒布し尽くすことができました!</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xd7f73e8)"><p lang="ja" dir="ltr">.<a href="https://twitter.com/hikalium?ref_src=twsrc%5Etfw">@hikalium</a> のOS Girls300部完売しました〜!🥳🥳🥳 <a href="https://t.co/0PZjReeHKe">pic.twitter.com/0PZjReeHKe</a></p>&mdash; Yuka Takahashi (@00_) <a href="https://twitter.com/00_/status/1117325907503378433?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>というわけで、ここまでの大雑把な流れと、ついさっきまでの当日の様子、反省点などをまとめておきたいと思います。</p> <h2>前日まで</h2> <p>正直言って、進捗は芳しくありませんでした。以下の画像は、執筆<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>のCode frequencyのグラフです。</p> <p><figure class="figure-image figure-image-fotolife" title="Code frequency of os-girls"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20190414/20190414210526.png" alt="f:id:hikalium:20190414210526p:plain" title="f:id:hikalium:20190414210526p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>Code frequency of os-girls</figcaption></figure></p> <p>どう見ても、締め切り直前にどかっと書いている様子がわかりますね。</p> <p>ちなみに、入稿は4/9に行いました。(印刷は日光企画さんにお願いしました。)</p> <p>元々は、<a href="http://www.nikko-pc.com/event-sime/2019/gijutsu.html">日光企画の技術書典のしめきり表</a>にある「40%OFF」つまり3/27に入稿できたらいいな、とか考えていたのですが、無理でした。ええ、無理は禁物です。</p> <p>結局、自分はもう真のしめきりがいつだか知っているのだから、それを騙すことはできないのです。ロジックは正直です。</p> <p>というわけで、滑り込みで入稿して、しかもその日の締め切り時間の数時間前に確認の電話があり</p> <p>「原稿の本文の一部が完全に崩れていて読めない」</p> <p>という衝撃的な事実がわかり、SATySFiで出力したものを入稿するなどという冒険をした自分を呪うなどしました。(日光企画さんにはお手数をおかけしました…丁寧な対応でほんと助かりました…)。</p> <p>とりあえず、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Mac">Mac</a>で「印刷」からpdfをエクスポートし直したものと、最悪のケースに備えて全ページを600dpiのjpgで出力したものを同封して再入稿するなど、バタバタとしたのち、連絡がなくて心配になりついに電話して確認したところ</p> <p>「いただいたデータで大丈夫でしたので当日お届けいたします!」</p> <p>と言っていただけて、やっと人心地ついたのでした。</p> <h2>前日準備</h2> <p>さて、これであとは人事を尽くして天命を、というところでしたが、ブースの設営もなにせ初めてでしたので、先人の知恵をインターネットで検索して、必要そうなものをリストアップして急遽買うなどしました。</p> <p>急遽買ったものとしては、ブックスタンド、おかねを入れる袋、コインケース、透明ブックカバーなどがありました。</p> <p>あと、現地には電源がないということだったので、大容量のモバイルバッテリーを買うなどしました。(元々欲しかったのでちょうどよかった。)</p> <p>さらには、前日になってはじめて「500円で頒布するならおつりの500円玉がたくさん必要では?」ということに気づき、焦って1000円を握りしめ、コンビニに走ってアイスを買うなどしました。</p> <h2>ブース環境ともちもの</h2> <p>ブースの環境としては、<a href="https://blog.techbookfest.org/2019/04/12/tbf06-short-notice/">運営からの注意事項</a>にもあった通り</p> <ul> <li>机半卓(横90センチ×奥行45センチ)椅子2脚</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Wi-Fi">Wi-Fi</a>はなし</li> <li>電源もない</li> <li>飲食は可能、ごみすて場なし</li> </ul> <p>という状況でした。</p> <p>持っていったものとしては、</p> <ul> <li>hikaliumステッカー全部(400より少し少ないくらいか?)</li> <li>目玉・ダブルクリップ(テーブルクロス固定等に使う)</li> <li>モバイルバッテリー(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%DE%A5%DB">スマホ</a>充電用)</li> <li>スケッチブック的ななにか(おしながきや完売表示に)</li> <li>ふせん(価格表示やとりおき表示に)</li> <li>テーブルクロス(みんなやってる)</li> <li>マスキングテープ(テーブルクロスとかブックスタンドを固定できる)</li> <li>油性マーカ(おしながき書いたり)</li> <li>ノート(おかねの管理等)</li> <li>ブックスタンド(サンプル展示用)</li> <li>ブックカバー(サンプル用)</li> <li>名刺(あるといいかも)</li> <li>のみもの(水がないと死ぬ)</li> <li>おかね・コインケース・お金を入れる袋(お金はだいじ)</li> </ul> <p>という感じでした。</p> <p>あと、本体としてのPCとか、通常の装備を持って行きました。</p> <h2>当日</h2> <p>なんとか起床に成功し現着。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xdb983e0)"><p lang="ja" dir="ltr">無事着いた!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> 6 <a href="https://t.co/R8cKKDb2Of">pic.twitter.com/R8cKKDb2Of</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117231044724289537?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>本も無事に机の下に配送されていて、ほんと印刷所の方と運営スタッフありがとうという気持ちになった。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xd7d87b0)"><p lang="ja" dir="ltr">そして本も無事着いていた!想像以上の出来!たまには物理世界もいいものですね!!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> 6 <a href="https://t.co/VScHsLZUHH">pic.twitter.com/VScHsLZUHH</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117231256234631168?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>ほぼ初めての印刷入稿だったが、想像以上に「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%F4%B3%D8%A5%AC%A1%BC%A5%EB">数学ガール</a>」感を出せていたのでとてもよかった。マットPP貼り大好き!</p> <p>そして、ブース設営完了。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xe54c980)"><p lang="ja" dir="ltr">OSGirls, う35で販売します!<br>画像は売り子をしてくれる <a href="https://twitter.com/00_?ref_src=twsrc%5Etfw">@00_</a> です!<br>かんたん後払い、Pixiv pay対応なので小銭がない場合はそちらも使っていただけると!!<br>よろしくお願いします!!!<a href="https://twitter.com/hashtag/%E6%8A%80%E8%A1%93%E6%9B%B8%E5%85%B8?src=hash&amp;ref_src=twsrc%5Etfw">#技術書典</a> 6 <a href="https://t.co/DqpRbK5tie">pic.twitter.com/DqpRbK5tie</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117246238515052544?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>(このあと、windholeの風穴さんから、吊るタイプのpopハンガーをお借りして、ブースがさらにパワーアップしました!)</p> <p>ちなみに、売り子はセキュキャン同期で、かつ<a class="keyword" href="http://d.hatena.ne.jp/keyword/CERN">CERN</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/LLVM">LLVM</a>を書いていたことで知られている<a href="https://twitter.com/00_">Yuka Takahashi</a>氏にお願いしました。ほんとに優秀で超助かりました。ありがとう。popなどはyuka氏が書いてくれました。</p> <p>技術書典の会場はラッシュ時の中央線並みに混雑し、かつとても広く、出口は1箇所しかないため、会場外に昼食やトイレに行く場合はものすごく時間がかかります。それを考えると、売り子なしの1人でブースを切り盛りするのは不可能です。かならず売り子はだれかにお願いしましょう。</p> <p>そして、あとは売るだけ。とにかく売る。お金を受け取って商品を渡す。簡単後払いのバーコードを読んでもらって確認画面を見て商品をわたす。それの繰り返しです。</p> <p>弊ブースでは、現金・かんたん後払い・Pixiv Payの3種の支払い方法に対応していました。</p> <p>内訳としては、簡単後払いが予想以上に多く、ざっと確認した限りで100名以上の方が利用してくださっていました。</p> <p>Pixiv payは2名ほどでしたが利用者がおり、それ以外はすべて現金だったようです。</p> <p>(かんたん後払いアプリ、販売数や金額の統計が見られないのでつらいです。とても便利なアプリなので、その部分を改善していただけるとより使いやすくなると思います!)</p> <p>現金の支払いについては、Pixiv payのレジ機能で一応カウントしていたのですが、応対が忙しくなるにつれ、入力漏れが増えてきてしまいつらかったです。</p> <h2>当日ネタと終焉</h2> <p>あとは、ステッカーを50枚強奪していく悪いオタクが出現したり(きちんと対価はいただいているのでよいのです)</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xde854d0)"><p lang="ja" dir="ltr">女子高生直伝のテクニックですが、ヘ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%B4">アゴ</a>ムはステッカーをまとめるのに使える <a href="https://t.co/bBnKr3e9cA">pic.twitter.com/bBnKr3e9cA</a></p>&mdash; マグロ 頭部 (@MysticDoll) <a href="https://twitter.com/MysticDoll/status/1117265008763654144?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>差し入れをさまざまな方からいただいたり(差し入れてくださった皆さま、ありがとうございました!!)</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xe589200)"><p lang="ja" dir="ltr">差し入れの八つ橋!ありがとうございます! <a href="https://t.co/vPHejIBYu7">pic.twitter.com/vPHejIBYu7</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117316090327994369?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>そうしていたらいつのまにか机の上の在庫だけになり、</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xdcd5268)"><p lang="ja" dir="ltr">売り切れが見えてきた。あとこれだけの在庫限りです。 <a href="https://t.co/tgu5WbF4c5">pic.twitter.com/tgu5WbF4c5</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117313162368258048?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>そして完売。(ちなみに最後の一冊は、BitNOSの<a href="https://twitter.com/uchan_nos">uchan</a>さんが買おうとしていたら、隣のブースの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B0%C5%B9%F5%C4%CC%BF%AE%C3%C4">暗黒通信団</a>の方が颯爽とお買い上げしていきました。)</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xe411110)"><p lang="ja" dir="ltr">完全に終了した図です。ありがとうございました。<br>(本も300はけてびっくりだが、ステッカーも400ほとんどはけて衝撃的である。ほんとみなさんありがとうございます…次も頑張って書くぞ!!!) <a href="https://t.co/0bm8zP80WJ">pic.twitter.com/0bm8zP80WJ</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1117338191193710593?ref_src=twsrc%5Etfw">April 14, 2019</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>私もまさか完売するとは思っておらず、完全にBOOTH倉庫に直接発送できるサービスを使おうと思っていたのですが、使わずに済んでしまいました。びっくり。</p> <p>とはいえ、早く売り切れになりすぎることもなく、大幅に売れ残ることもなく、ちょうどよいか少し少ない、といった程度の冊数だったのではないかな、と思います。</p> <p>ちなみに、この記事を書いている、技術書典終了後の夜のチェック数はこんな感じでした。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20190414/20190414215653.png" alt="f:id:hikalium:20190414215653p:plain" title="f:id:hikalium:20190414215653p:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2>まとめ・反省点</h2> <p>結論としては、本当に最高の1日でした。まさか、こんなにも自分の書いた文章を買ってくださる方がたくさん、しかもリアルワールドに存在するなんて、すごくすごくありがたいことです。</p> <p>正直、もっと本のクオリティをあげたかったな、というところが最大の反省点に今はなっています。</p> <p>OSGirlsを読んでくださったみなさまはお気づきかと思いますが、実は結構内容が不足していたり、唐突な終わり方になってしまったりしています。特に、途中で唐突に出てくる <code>elf.h</code> や <code>build.sh</code> なんて、本のどこを読んでも書いてありません。ええ、これは私の能力不足です。</p> <p>サポートページへのリンクもつくったのですが、内容がゼロです。本当にすみません。一週間中に充実させます。(少なくとも、本の中でアキとミカが体験したことをできるだけの情報は提示します。)</p> <p>…とまあ、たいへん穴だらけの作品だったわけですが、それでもみなさんが私に期待して、購入してくださったということがとても嬉しいですし、原動力にもなりました。</p> <p>秋の技術書典では、もちろん続きを出したいと思います。今度は、さらに盛りだくさんで、充実した内容になるようがんばります。</p> <p>というわけで、今後も <code>OSGirls</code> は続けて行きたいと思いますので、みなさまどうかよろしくお願いいたします。</p> <h2>デジタルデータ販売</h2> <p>BOOTHにてPDFデータの販売を開始しました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fbooth.pm%2Fja%2Fitems%2F1317230" title="OSGirls - hikalium - BOOTH" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://booth.pm/ja/items/1317230">booth.pm</a></cite></p> <p>こちらのデータは、現在は技術書典6で頒布した冊子と完全に同一の内容ですが、今後内容を更新した際には最新の版に更新してゆく予定です。</p> <p>次の技術書典に向けて応援してくださるみなさまや、物理本を買うことができなかったので内容が気になる方はぜひ購入していただけるとありがたいです。</p> <h2>謝辞</h2> <p>OSGirlsの表紙絵は、私の古くからの友人である @From_boku_To_ 氏に描いていただきました。忙しい中、無理を言って描いてくださってありがとうございました。今後ともよろしくお願いします(笑)。</p> <p>技術書典6の販売ブースでは, <a href="https://twitter.com/00_">Yuka Takahashi</a>氏にお手伝いいただきました。完璧なオペレーションで私が離席中も一切心配する必要がありませんでした。本当に感謝です。</p> <p>また、何度か執筆の場を設けてくださった<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A5%A4%A5%DC%A5%A6%A5%BA">サイボウズ</a>の風穴さん( <a href="https://twitter.com/windhole">@windhole</a> )にも大いに感謝しています。また執筆会を設けていただけると助かります!</p> <p>そして、今回の作品の形態のベースとなった「<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BF%F4%B3%D8%A5%AC%A1%BC%A5%EB">数学ガール</a>」作者の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B7%EB%BE%EB%B9%C0">結城浩</a>氏と、私をOSの世界に引き込んでくれた「30日でできる!OS自作入門」作者の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%EE%B9%E7%BD%A8%BC%C2">川合秀実</a>氏にも深くお礼を申し上げます。ありがとうございました。</p> <h2>次回に向けて</h2> <p>技術書典7でもOSGirlsを出すぞー!!!</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20190414/20190414223445.jpg" alt="f:id:hikalium:20190414223445j:plain" title="f:id:hikalium:20190414223445j:plain" class="hatena-fotolife" itemprop="image"></span></p> hikalium compilium v2 におけるdeclarationの実装 hatenablog://entry/10257846132687497757 2018-12-25T22:58:17+09:00 2018-12-26T20:34:49+09:00 この記事は、C言語 Advent Calendar 2018のうち、3連続素数和が素数になる最小の数番目の記事です。 …といったものの、かなり公開が遅れてしまいました。ごめんなさい…(SECCON国内決勝とかぶったりした&計画性がないのが原因です。) また、言語実装アドベントカレンダーのほうでもcompiliumに関連する内容の記事を書きましたので興味があればご参照ください。 hikalium.hatenablog.jp はじめに Cコンパイラを実装したことのあるみなさんも、変数の宣言や型の宣言を行うdeclarationの実装で詰まってしまった方は多いのではないでしょうか。 この記事では、C… <p>この記事は、<a href="https://qiita.com/advent-calendar/2018/c_lang">C言語 Advent Calendar 2018</a>のうち、<code>3連続素数和が素数になる最小の数</code>番目の記事です。</p> <p>…といったものの、かなり公開が遅れてしまいました。ごめんなさい…(SECCON国内決勝とかぶったりした&amp;計画性がないのが原因です。)</p> <p>また、言語実装<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%C9%A5%D9%A5%F3%A5%C8%A5%AB%A5%EC%A5%F3%A5%C0%A1%BC">アドベントカレンダー</a>のほうでもcompiliumに関連する内容の記事を書きましたので興味があればご参照ください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2018%2F12%2F07%2F210646" title="compilium v2 (in progress)の工夫点 - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2018/12/07/210646">hikalium.hatenablog.jp</a></cite></p> <h2>はじめに</h2> <p>C<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>を実装したことのあるみなさんも、変数の宣言や型の宣言を行うdeclarationの実装で詰まってしまった方は多いのではないでしょうか。 この記事では、Cのdeclarationをインクリメンタルにうまく実装する方法について検討した記録<s>と、その実装を一部途中まで進めた話</s>を紹介します。</p> <p>仕様についてはもう知ってるので説明不要だよ!というプロの皆様は、下の方にある「インクリメンタルに実装しよう!」を読んでいただくと時間の節約になります。</p> <h2>まずはdeclarationについて知る</h2> <p>何はともあれまずは仕様書を読んで、おおまかに仕様を理解します。いくらインクリメンタルに開発するとはいえ、最終的な到達目標をきちんと理解していないことには、途中で立ち行かなくなってしまいますからね。 というわけで、declarationとは一体どのようなものか、仕様書に沿って見ていくことにしましょう。</p> <h3>そもそもdeclarationってなんだ?</h3> <p><a href="http://www.iso-9899.info/n1570.html#6.7p5">仕様書</a>によれば、declarationとは、いくつかのidentifierについてその解釈や属性を与えるもので、具体的には</p> <ul> <li>ローカル変数や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%ED%A1%BC%A5%D0%A5%EB%CA%D1%BF%F4">グローバル変数</a>などの記憶領域を持つオブジェクト</li> <li>関数</li> <li>列挙定数</li> <li>typedef名</li> </ul> <p>となるような識別子を宣言するものであると書かれています。というわけで、declarationには必ず名前となる識別子が一つ以上、それに対応する属性もいっしょに書かれていることになります。 (ちなみに、_Static_assertも構文上はdeclarationに入っていてこれは識別子を持たないのですが、実質的にはdeclarationではないのでここでは説明しません。)</p> <p>declarationの最もトッ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%EC%A5%D9">プレベ</a>ルな構文としては、以下のようになっています。(末尾のoptは省略可能という意味です。)</p> <pre class="code" data-lang="" data-unlink>declaration: declaration-specifiers init-declarator-listopt ; static_assert-declaration declaration-specifiers: storage-class-specifier declaration-specifiersopt type-specifier declaration-specifiersopt type-qualifier declaration-specifiersopt function-specifier declaration-specifiersopt alignment-specifier declaration-specifiersopt init-declarator-list: init-declarator init-declarator-list , init-declarator init-declarator: declarator declarator = initializer</pre> <p>…といって理解できればみんな困らないので、上の構文を<code>int a = 3, *b;</code>について図示してみたものが以下です。</p> <p><figure class="figure-image figure-image-fotolife" title="declaration of int a = 3, *b;"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181224/20181224205850.png" alt="f:id:hikalium:20181224205850p:plain" title="f:id:hikalium:20181224205850p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>declaration int a = 3, *b;</figcaption></figure></p> <p>みなさんご存知の通り、<code>int a = 3, *b;</code>を解釈すると、初期値3をもつint型の変数aと、int型へのポインタ変数b、が宣言されますね。</p> <p>構文的な重要ポイントとしては、</p> <ul> <li><code>declaration</code>は<code>declaration-specifiers</code>がひとつと、<code>init-declarator</code>が複数合わさったものであり</li> <li><code>init-declarator</code> は<code>declarator</code>と、任意で<code>initializer</code>をつけることができる</li> </ul> <p>ということです。とりあえず、最初はinitializerのことは無視することにして、いまここで最も重要なことは</p> <ul> <li><code>declaration-specifiers</code> + <code>declarator</code> でひとつの宣言が出来上がる</li> </ul> <p>ということです。では<code>declaration-specifiers</code>と<code>declarator</code>について見ていくことにしましょう。</p> <h3><code>declaration-specifiers</code>ってなんだ?</h3> <p>上の構文</p> <pre class="code" data-lang="" data-unlink>declaration-specifiers: storage-class-specifier declaration-specifiersopt type-specifier declaration-specifiersopt type-qualifier declaration-specifiersopt function-specifier declaration-specifiersopt alignment-specifier declaration-specifiersopt</pre> <p>からわかることとしては、なんとかspecifierとか、なんとかqualifierというのが1つ以上並んだものが<code>declaration-specifiers</code>です。</p> <h4>type-specifier</h4> <p>たとえば、<code>type-specifier</code>は、よくみる<code>int</code>や<code>char</code>とか<code>unsigned</code>とかのことです。</p> <pre class="code" data-lang="" data-unlink>type-specifier: void char short int long float double signed unsigned _Bool _Complex atomic-type-specifier struct-or-union-specifier enum-specifier typedef-name</pre> <p>また、これにはstructやunion, <a class="keyword" href="http://d.hatena.ne.jp/keyword/enum">enum</a>の型情報も含まれます。つまり、<code>struct KV{const char *key; void *v;}</code>とかは<code>type-specifier</code>, 中でも<code>struct-or-union-specifier</code>に含まれるわけです。</p> <p>さらに、typedefによってつけられた型の別名もここに入ります(<code>typedef-name</code>)。typedefのせいで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>のパーサはパースしながらdeclarationを解釈しなくてはいけないのです。まあ、最初は実装しなくてもいいのですが。</p> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/enum">enum</a>-specifier</h4> <p><code>enum E{kKey1 = 3, kKey2}</code> とかのことです。</p> <h4>type-qualifier</h4> <p><code>const</code>とか<code>volatile</code>とかです。</p> <h4>function-specifier</h4> <p><code>inline</code>か<code>_Noreturn</code>のことです。</p> <h4>storage-class-specifier</h4> <p><code>typedef</code>とか<code>extern</code>とか<code>static</code>とかのことです。</p> <h4><code>declaration-specifiers</code>の衝撃の事実</h4> <p>もっと詳しく知りたい方は、仕様書を適当に読んでほしいのですが、面白いネタとしてはこんな話があります。</p> <p>なんと、上記のspecifierたちは、一部の例外を除いて順序を自由に入れ替えてよいことになっています。したがって、 <code>unsigned long const int long extern</code>とか書いても全く問題ないわけです。(人間には厳しいですが。)</p> <h3><code>declarator</code>ってなんだ?</h3> <p>正直、<code>declaration-specifiers</code>はやるだけです。簡単です。でもこっちの<code>declarator</code>は、少し冷静になってしっかり理解をする必要があります。</p> <p>まず<code>declarator</code>そのものは単純明快です。</p> <pre class="code" data-lang="" data-unlink>declarator: pointeropt direct-declarator pointer: * type-qualifier-listopt * type-qualifier-listopt pointer</pre> <p>これは要するに、ポインタの<code>*</code>(とその修飾子列の組)が0個以上並んだあとに、<code>direct-declarator</code>が続くよ、という意味です。たとえば、<code>int *b;</code>とかなら</p> <p><figure class="figure-image figure-image-fotolife" title="int *b;"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181224/20181224215246.png" alt="f:id:hikalium:20181224215246p:plain" title="f:id:hikalium:20181224215246p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>int *b;</figcaption></figure></p> <p>という感じになります。この例は、<code>direct-declarator</code>には識別子が一つだけくるケースになっています。</p> <p>ところが、<code>direct-declarator</code>はそう単純ではありません。</p> <pre class="code" data-lang="" data-unlink>declarator: pointeropt direct-declarator direct-declarator: identifier ( declarator ) direct-declarator [ type-qualifier-listopt assignment-expressionopt ] direct-declarator [ static type-qualifier-listopt assignment-expression ] direct-declarator [ type-qualifier-list static assignment-expression ] direct-declarator [ type-qualifier-listopt * ] direct-declarator ( parameter-type-list ) direct-declarator ( identifier-listopt )</pre> <p>なんと<code>direct-declarator</code>は自身と<code>declarator</code>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>的に含むことができます。 (これはつまり、<code>declarator</code>は<code>declarator</code>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>的に含むことができるということです。) したがって、単に<code>declarator</code>と呼んでしまっては、<code>declarator</code>の全体をさすのか、部分を指すのか分かりづらくなってしまいます。</p> <p>というわけで、ある<code>declaration</code>において、他のどの<code>declarator</code>にも含まれないような<code>declarator</code>のことを、仕様書の言葉を借りてfull-declaratorと呼ぶことにしましょう。</p> <p>例としては、</p> <ul> <li><code>int *f(int a, int b);</code>の<code>*f(int a, int b)</code></li> <li><code>char m[3][4];</code>の<code>m[3][4]</code></li> <li><code>void (*fp)(int a);</code>の<code>(*fp)(int a);</code></li> </ul> <p>がfull-declaratorにあたります。</p> <p><code>declarator</code>の構文をじっくり見ていただくとわかるのですが、いくら<code>declarator</code>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%FE%A4%EC%BB%D2">入れ子</a>になっても、ひとつのfull-declaratorについて、<code>identifier</code>が現れるのはちょうどひとつになることが分かります。</p> <p>つまり、declaratorは、宣言の情報のうち</p> <ul> <li>ポインタ</li> <li>配列</li> <li>関数</li> <li>そしてひとつの識別子(declaratonが定義しようとしている名前)</li> </ul> <p>を表現することがわかります。</p> <h3>declarationの構文を書き下してみる</h3> <p>さて、ここまでの情報をもとに、declarationをもう少しわかりやすい形で書き直してみることにしましょう。</p> <p>結局のところ、declarationは、なんらかの識別子と、その型や属性をペアにしたものを複数同時に表現する構文なわけです。 なぜ複数になるのかというと、init-declarator-listによって、ひとつのdeclarationの中に複数のfull-declarationが入ることがあるためなのですが、とりあえずひとつの識別子について型や属性を知りたいので、ここでは単純に<code>declaration = declaration-specifiers + full-declarator</code>で構成されると考えて説明します。</p> <p>まず、declarationの各部分を、以下のような文字でおくことにします。</p> <pre class="code" data-lang="" data-unlink>T: declaration-specifier D: declarator P: pointer E: direct-declaratorの各断片 I: Identifier </pre> <p>そしてこれらを用いて、各構文を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%B5%B5%AC%C9%BD%B8%BD">正規表現</a>風に記述するとこんな感じになります。</p> <pre class="code" data-lang="" data-unlink>declaration = TD D = P*[I|(D)]E*</pre> <h4>最もシンプルなケース</h4> <p>たとえば、<code>int a;</code>というdeclarationは、書き下すと<code>TI</code>になります。 <code>int a;</code>を回りくどく書けば、<code>a is_a(int)</code>ですから<code>I(t): Iが識別子Xだとして、X is_a(t) を返す</code>と考えればよさそうです。</p> <h4>ポインタの適用順</h4> <p>次のケースは、ポインタの場合です。たとえば、<code>int * const * p;</code>などを考えてみましょう。 ちなみに、これも回りくどく書けば<code>p is_a(pointer_of(const_pointer_of(int)))</code>となるのはすぐわかるでしょう。 念の為言っておきますと、ポインタ変数そのものは書き換えられますが、1回<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%EA%A5%D5%A5%A1%A5%EC%A5%F3%A5%B9">デリファレンス</a>したものはconstなポインタ変数になるので書き換えできず、2回<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%EA%A5%D5%A5%A1%A5%EC%A5%F3%A5%B9">デリファレンス</a>したものはただのint型なので書き換えられます。</p> <p>さて、説明を容易にするため、PやEについて、左から右に番号を振ることにします。つまり、</p> <pre class="code" data-lang="" data-unlink>declaration = T P_1 P_2 ... [I | (D)] E_1 E_2 ...</pre> <p>という感じです。</p> <p>このノリでいくと、</p> <pre class="code" data-lang="" data-unlink>int * const * p; = T P_1 P_2 I T: int P_1: * const P_2: * I: p</pre> <p>ということになります。</p> <p>さて、Pは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%FE%A4%EC%BB%D2">入れ子</a>にできますから、</p> <pre class="code" data-lang="" data-unlink>P(t): pointer_of(t)を返す。(constがついているならconst_pointer_of(t)を返す)</pre> <p>とおくと都合がよさそうです。</p> <p>この型が<code>p is_a(pointer_of(const_pointer_of(int)))</code>であることを考えると、連続したPは</p> <pre class="code" data-lang="" data-unlink>I(P_2(P_1(T))) = I(P_2(P_1(int))) = I(P_2(const_pointer_of(int))) = I(pointer_of(const_pointer_of(int))) = p is_a(pointer_of(const_pointer_of(int)))</pre> <p>というように、<code>P_1 P_2 P_3 =&gt; ...P_3(P_2(P_1(t)))</code>と評価すればうまくいきそうです。</p> <h4>配列の適用順</h4> <p>じゃあ次は配列いってみましょうか。</p> <p>たとえば、よくある<code>int arr[3][5];</code>は、<code>arr is_a(Array(size: 3, type: Array(size: 5, type: int)))</code>という意味です。</p> <p>ということで<code>E(t): Eがarray declarator [n] ならば、Array(size: n, type: t)を返す。</code>と考えればよさそうです。</p> <p>適用順としては、 <code>E_1 E_2 E_3 =&gt; E_1(E_2(E_3(t)))</code>とすれば、</p> <pre class="code" data-lang="" data-unlink>I(E_1(E_2(T))) = I(E_1(E_2(int))) = I(E_1(Array(size: 5, type: int))) = I(Array(size: 3, type: Array(size: 5, type: int))) = arr is_a(Array(size: 3, type: Array(size: 5, type: int)))</pre> <p>となってうまくいきそうです。</p> <h4>関数の場合</h4> <p>関数も配列と同じdirect-declaratorに含まれるので、配列の適用順を参考にすれば <code>E(t): Eがfunction declarator (arg1, arg2, ...) ならば、Func(returns: t, args: (arg1, arg2, ...)) を返す。</code> とすれば、たとえば<code>void f(int a);</code>などは</p> <pre class="code" data-lang="" data-unlink>I(E_1(T)) = I(E_1(void)) = I(Func(returns: void, args: (int a)) = f is_a(Func(returns: void, args: (int a))</pre> <p>となってうまくいきそうです。(引数に関しては、declarationを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>的に適用すれば目的の結果が得られるので今回はそのままにしています。)</p> <p>ところで、<a href="http://www.iso-9899.info/n1570.html#6.7.6.2p1">関数を要素とするような配列</a>や、<a href="http://www.iso-9899.info/n1570.html#6.7.6.3p1">配列・関数を戻り値とするような関数</a>をつくることはできてはならないと仕様書に明記されています。</p> <p>したがって、Eが関数の場合にE同士がネストするケースをここで紹介することは不可能です。</p> <h4><code>E, P, (D)|I</code>の適用順</h4> <p>たとえば、みんな大好き</p> <pre class="code" data-lang="" data-unlink>void (*signal(int sig, void (*func)(int)))(int);</pre> <p>は、書き下すと</p> <pre class="code" data-lang="" data-unlink>T1(P2_1 I2 E2_1)E1_1</pre> <p>となります。そして、ここから導ける型としては</p> <pre class="code" data-lang="" data-unlink>signal is_a( Func( returns: pointer_of(Func(returns: void, args: (int))), args: (int sig, void (*func)(int)) ) )</pre> <p>となることから、逆に辿って考えてみると、</p> <pre class="code" data-lang="" data-unlink>signal is_a( Func( returns: pointer_of(Func(returns: void, args: (int))), args: (int sig, void (*func)(int)) ) ) = I2( Func( returns: pointer_of(Func(returns: void, args: (int))), args: (int sig, void (*func)(int)) ) ) = I2(E2_1( pointer_of(Func(returns: void, args: (int))) )) = I2(E2_1(P2_1( Func(returns: void, args: (int)) ))) = I2(E2_1(P2_1(E1_1( void )))) = I2(E2_1(P2_1(E1_1(T))))</pre> <p>となります。つまり、適用順は</p> <pre class="code" data-lang="" data-unlink>T -&gt; Pの小さい方から大きい方 -&gt; Eの大きい方から小さい方 -&gt; DがあればD -&gt; I</pre> <p>という順番になるんですね。</p> <h2>インクリメンタルに実装しよう!</h2> <p>お疲れ様でした。長い説明に付き合ってくださりありがとうございました。(理解しづらいところがあればぜひコメントをください。)</p> <p>では、簡単なケースからインクリメンタルに実装してみましょう!</p> <h3><code>int a;</code>や<code>char c;</code>のような<code>TI</code>型を処理できるようにする</h3> <p>Tにあたるものとして、BaseTypeという構造体をつくります。 とりあえず、type_specifierひとつだけがBaseTypeだと考えましょう。(int, char, voidとかが表現できるね!)</p> <pre class="code" data-lang="" data-unlink>struct BaseType { struct Token *type_specifier; };</pre> <p>次に、D: declaratorにあたるものとして、Declarator構造体をつくりましょう。 最初は簡単な例として<code>int a;</code>が表現できればよいので、identifierだけ入れることにしましょう。</p> <pre class="code" data-lang="" data-unlink>struct Declarator { struct Token *identifier; };</pre> <p>これらの組をDeclarationPairとしましょう。</p> <pre class="code" data-lang="" data-unlink>struct DeclarationPair { struct BaseType *base_type; struct Declarator *decltor; };</pre> <p>これで、BaseTypeとDeclaratorの組<code>TI</code>の形式で表現できる宣言をDeclarationPairで表現できるようになりました。 パーサは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>下降法で書くだけなので省略します。</p> <p>DeclarationPairから作成される、型情報の構造体について考えます。</p> <p>型情報は統一的にTypeという構造体で表すことにして、</p> <pre class="code" data-lang="" data-unlink>struct Type { enum { kBaseType, kIdentifierAttr, } subtype; struct BaseType *base_type; struct Token *identifier; struct Type *next; }</pre> <p>というふうにしておきます。nextは、<code>pointer_of(t)</code>や<code>ident is_a(t)</code>のtにあたるものです。</p> <p>そしてDeclarationPairからTypeを作るような関数をつくります。</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarationPair(struct DeclarationPair *decl_pair) { struct Type *type = AllocAndInitBaseType(decl_pair-&gt;base_type); type = AllocAndInitIdentifierAttr(decl_pair-&gt;decltor-&gt;identifier, type); return type; }</pre> <p>これだけで、ひとまず<code>int a;</code>とか<code>char c;</code>とかはいけるようになります。やったね!</p> <h3><code>int **pp;</code>のような<code>TP*I</code>型を処理できるようにする</h3> <p>つぎは、ポインタに対応しましょう。最初は<code>*const</code>などのポインタ属性に対応しないと割り切ってしまえば<code>*</code>の個数を数えればいいので、Declaratorに<code>*</code>の個数を格納するメンバを追加します。</p> <pre class="code" data-lang="" data-unlink>struct Declarator { int pointer_count; // new! struct Token *identifier; };</pre> <p>そして、Typeにも型だけ追加しておきます。</p> <pre class="code" data-lang="" data-unlink>struct Type { enum { kBaseType, kIdentifierAttr, kPointerType, // new! } subtype; struct BaseType *base_type; struct Token *identifier; struct Type *next; }</pre> <p>そして、<code>CreateTypeFromDeclarationPair()</code>にコードを追加します。</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarationPair(struct DeclarationPair *decl_pair) { struct Type *type = AllocAndInitBaseType(decl_pair-&gt;base_type); for(int i = 0; i &lt; decl_pair-&gt;decltor-&gt;pointer_count){ // this loop type = AllocAndInitPointerType(type); } type = AllocAndInitIdentifierAttr(decl_pair-&gt;decltor-&gt;identifier, type); return type; }</pre> <p>これで、<code>int **pp;</code>とかが処理できますね!</p> <h3><code>int *arr[2][3];</code>のような<code>TP*IE*</code>(Eは配列)を処理できるようにする</h3> <p>ポインタができたら、次は配列ですね。配列は、要<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>に整数のみをとると仮定しましょう。</p> <p>とりあえず、direct-declaratorに対応する構造体をつくります。</p> <pre class="code" data-lang="" data-unlink>struct DirectDeclarator { enum { kArrayDeclarator, } type; int size; }</pre> <p>そして、DirectDeclaratorの列<code>E*</code>を格納するメンバをDeclaratorに追加します。</p> <pre class="code" data-lang="" data-unlink>struct Declarator { int pointer_count; struct Token *identifier; struct List *direct_declarators; // List of DirectDeclarator };</pre> <p>ここでは、Listの実装の詳細については述べません。</p> <p>そして、<code>CreateTypeFromDeclarationPair()</code>にコードを追加します。</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarationPair(struct DeclarationPair *decl_pair) { struct Type *type = AllocAndInitBaseType(decl_pair-&gt;base_type); for(int i = 0; i &lt; decl_pair-&gt;decltor-&gt;pointer_count){ type = AllocAndInitPointerType(type); } for(int i = GetSizeOfList(decl_pair-&gt;decltor-&gt;direct_declarators); i &gt;= 0; i--) { // this loop struct DirectDeclarator **dd = GetNodeAt(decl_pair-&gt;decltor-&gt;direct_declarators, i); if(dd-&gt;type == kArrayDeclarator) type = AllocAndInitArrayType(dd-&gt;size, type); } type = AllocAndInitIdentifierAttr(decl_pair-&gt;decltor-&gt;identifier, type); return type; }</pre> <p>これで、<code>int *arr[2][3];</code>とかが処理できますね!</p> <h3><code>int f(int c);</code>のような<code>TP*IE*</code>(Eは関数)を処理できるようにする</h3> <p>同様にして、関数も処理できるようにしましょう。 とりあえず、direct-declaratorにメンバを追加します。</p> <pre class="code" data-lang="" data-unlink>struct DirectDeclarator { enum { kArrayDeclarator, kFuncDeclarator, // new! } type; int size; struct List *args; // new! }</pre> <p>一応argsもつけましたが、最初はargsは真面目にチェックしなくてよいと思います。また、argsのパースや型情報への変換もここでは扱いません。そんなに難しくないのですぐにできると思います。</p> <p>そして、<code>CreateTypeFromDeclarationPair()</code>にコードを追加します。かんたんですね!</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarationPair(struct DeclarationPair *decl_pair) { struct Type *type = AllocAndInitBaseType(decl_pair-&gt;base_type); for(int i = 0; i &lt; decl_pair-&gt;decltor-&gt;pointer_count){ type = AllocAndInitPointerType(type); } for(int i = GetSizeOfList(decl_pair-&gt;decltor-&gt;direct_declarators); i &gt;= 0; i--) { // this loop struct DirectDeclarator **dd = GetNodeAt(decl_pair-&gt;decltor-&gt;direct_declarators, i); if(dd-&gt;type == kArrayDeclarator) type = AllocAndInitArrayType(dd-&gt;size, type); if(dd-&gt;type == kFuncDeclarator) type = AllocAndInitFuncType(type, dd-&gt;args); // here! } type = AllocAndInitIdentifierAttr(decl_pair-&gt;decltor-&gt;identifier, type); return type; }</pre> <p>これで<code>int f(int c);</code>も<code>int **f();</code>とかも処理できるんですよ。すごくないですか!</p> <p>ちなみに、この変換コードでは、先ほど説明したような、関数の戻り値に関数/配列を指定できない、配列の要素型に関数を指定できないというチェックを行なっていません。 チェックを追加するのはとてもかんたんなので、読者への課題とします。(最初はやらなくていいと思いますよ!)</p> <h3>ネストしたdeclaratorに対応する</h3> <p>さて、みんな大好き<code>signal</code>の定義をパースできるまであともう少しです!ネストしたdeclaratorに対応できれば、表現力はぐっと向上します。</p> <p>まず、ネストしたdeclaratorを表現できるようにdeclaratorを修正します。</p> <pre class="code" data-lang="" data-unlink>struct Declarator { int pointer_count; struct Token *identifier; struct Declarator *next; // here! struct List *direct_declarators; };</pre> <p>例によりパーサは書けると思うので省略します。</p> <p>そして、<code>CreateTypeFromDeclarationPair()</code>から関数を切り出して、ネストにうまく対応できるように準備します。(以下のコードは、一つ前のコードと等価な動作をします)</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarator(struct Declarator *decltor, struct Type *type) { for(int i = 0; i &lt; decltor-&gt;pointer_count){ type = AllocAndInitPointerType(type); } for(int i = GetSizeOfList(decltor-&gt;direct_declarators); i &gt;= 0; i--) { struct DirectDeclarator **dd = GetNodeAt(decltor-&gt;direct_declarators, i); if(dd-&gt;type == kArrayDeclarator) type = AllocAndInitArrayType(dd-&gt;size, type); if(dd-&gt;type == kFuncDeclarator) type = AllocAndInitFuncType(type, dd-&gt;args); } return AllocAndInitIdentifierAttr(decltor-&gt;identifier, type); } struct Type *CreateTypeFromDeclarationPair(struct DeclarationPair *decl_pair) { struct Type *type = AllocAndInitBaseType(decl_pair-&gt;base_type); return CreateTypeFromDeclarator(decl_pair-&gt;decltor, type); }</pre> <p>そして、もしもネストしていたら、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>的に<code>CreateTypeFromDeclarator()</code>を呼び出すようにします。</p> <pre class="code" data-lang="" data-unlink>struct Type *CreateTypeFromDeclarator(struct Declarator *decltor, struct Type *type) { for(int i = 0; i &lt; decltor-&gt;pointer_count){ type = AllocAndInitPointerType(type); } for(int i = GetSizeOfList(decltor-&gt;direct_declarators); i &gt;= 0; i--) { struct DirectDeclarator **dd = GetNodeAt(decltor-&gt;direct_declarators, i); if(dd-&gt;type == kArrayDeclarator) type = AllocAndInitArrayType(dd-&gt;size, type); if(dd-&gt;type == kFuncDeclarator) type = AllocAndInitFuncType(type, dd-&gt;args); } if(decltor-&gt;next) return CreateTypeFromDeclarator(decltor-&gt;next, type); // here! return AllocAndInitIdentifierAttr(decltor-&gt;identifier, type); }</pre> <p>なんとこれだけです!これだけで、あの奇怪な<code>void (*signal(int sig, void (*func)(int)))(int);</code>があなたの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>でも綺麗に解釈できるようになったのです!</p> <h2>まとめ</h2> <p>本当はここでcompiliumの実際のコードを貼ることになるはずだったのですが、そちらのほうはちょっと間に合いませんでした。申し訳ないです。(27日までには出したいですね。)</p> <p>実を言うと、上記のコードはブログの編集画面に直接打ち込んだため、バグや<a class="keyword" href="http://d.hatena.ne.jp/keyword/typo">typo</a>、ロジックのミスなどがあるかもしれません。発見しましたら、どうかそっと教えていただけると助かります。(報告、意見等は大歓迎です!<a href="https://twitter.com/hikalium">@hikalium</a>までお寄せください。)</p> <p>駆け足になりましたが、これで<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>のdeclarationの半分以上を理解していただけたならば私としても嬉しいですし、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>を書いていてdeclarationの処理で詰まっていた皆様の一助になればいいなと思っております。</p> <p>ということで、大変遅く&amp;長くなりましたが、これにてひとまずおしまいです。</p> <p>上の続きとしては、</p> <ul> <li>const pointer</li> <li>struct/union</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/enum">enum</a></li> <li>typedef</li> </ul> <p>などが待ち受けていますが、ここまでできれば比較的簡単にできると思います。(もちろん、落とし穴はたくさんありますが…。)</p> <p>長々と読んでいただき、ありがとうございました。</p> <p>来年もよいC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>自作ライフを楽しみましょう!</p> <h2>参考文献</h2> <ul> <li><a href="http://www.iso-9899.info/n1570.html">ISO/IEC 9899:201x Committee Draft April 12, 2011 N1570</a></li> </ul> hikalium SECCON CTF 2018 ( DOMESTIC )にチームBluemermaidで出て2位だった話 hatenablog://entry/10257846132689180335 2018-12-24T00:24:11+09:00 2018-12-24T00:55:51+09:00 2018-12-23に開催されたSECCON CTF 2018の国内決勝に、チームBluemermaidとして h_noson・うさぎ・srupとともに出場して、準優勝したようです。 準優勝の賞状 pic.twitter.com/aT7sUTgw2u— hikalium (@hikalium) December 23, 2018 ということで、一応Write-up的なものを書いておこうと思います。 概況 問題としては大きく三つ: 松島・天橋立・宮島に分かれており、最初は天橋立と宮島だけが開放されていて、松島は試合の途中で開放されました。 私は毎年のように、謎アーキテクチャバイナリ担当として雇わ… <p>2018-12-23に開催されたSECCON CTF 2018の国内決勝に、チームBluemermaidとして <a href="https://twitter.com/h_noson">h_noson</a>・<a href="https://twitter.com/a3VtYQo">うさぎ</a>・<a href="https://twitter.com/mmxsrup">srup</a>とともに出場して、準優勝したようです。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xdd56c18)"><p lang="ja" dir="ltr">準優勝の賞状 <a href="https://t.co/aT7sUTgw2u">pic.twitter.com/aT7sUTgw2u</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1076790190029426688?ref_src=twsrc%5Etfw">December 23, 2018</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>ということで、一応Write-up的なものを書いておこうと思います。</p> <h2>概況</h2> <p>問題としては大きく三つ: 松島・<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B6%B6%CE%A9">天橋立</a>・宮島に分かれており、最初は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B6%B6%CE%A9">天橋立</a>と宮島だけが開放されていて、松島は試合の途中で開放されました。 私は毎年のように、謎<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AD%A5%C6%A5%AF%A5%C1%A5%E3">アーキテクチャ</a>バイナリ担当として雇われていた(予選ではそれだけしか解けなかった)のですが、残念ながらそういった問題は出なかったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A1%BC%A5%C9%A5%B4%A5%EB%A5%D5">コードゴルフ</a>ができそうな3つ目の宮島を主にやっていました。</p> <h2>松島</h2> <p>松島は、ビデオポーカーの乱数に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>があるので、それをついてうまくいい手を出すとフラグがもらえたりディフェンスキーワードをサブミットできるよ(プログラムのバイナリは与えるよ)というものでした。</p> <p>これはうさぎさんとsrupさんがさくっと解いてくれたので詳細は各人に任せますが、どうも乱数に<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C0%C8%BC%E5%C0%AD">脆弱性</a>がありすぎ?だったようで、バイナリを解析せずとも4カードや<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%EB%A5%CF%A5%A6%A5%B9">フルハウス</a>を出せてしまったらしく、しかもディフェンスキーワードのサブミットフォームの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%F7%BF%AE%C0%E8">送信先</a>URLが常に同一だったため、一回解いてしまえばポーカーには一切触れず自動化できてしまうという代物だったようです。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B6%B6%CE%A9">天橋立</a></h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B6%B6%CE%A9">天橋立</a>は、ディフェンスポイントのみがある問題でした。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a> HELLというサイト名で、<a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS%C0%C8%BC%E5%C0%AD">XSS脆弱性</a>があるような任意のhtmlをアップロードできる仕組みになっていました。 そのhtmlはだれでもダウンロードでき、それに存在する<a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a>を他のチームは解くことができて、解かれてしまうとディフェンスポイントは入らないよーというルールでした。 具体的には、アップロード時の名前をディフェンスキーワードの文字列にすることで、その問題が解かれずに残っていると、ディフェンスポイントが入るという仕組みでした。</p> <p>というわけで、人々は最初、そこそこ難しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DA%A5%A4%A5%ED%A1%BC%A5%C9">ペイロード</a>を突っ込んだ時だけ<a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a>が発動するようなhtmlをあげておいて、ディフェンスキーワードが変わったら自分たちで解いて新しくアップロードしなおせばいいのだと考えていました。 ところがなんと、あるチームがアップロードしたhtmlは、そのチームが自ら解くことはできず、一方でタイトルはアップロード履歴画面から任意に変更できるという仕組みになっていたのです。 …そうすると、何が起こったか。</p> <p>どのチームも、そのチームだけが知っている特定のキーワードの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%CF%A5%C3%A5%B7%A5%E5%C3%CD">ハッシュ値</a>をhtmlに書いておき、それが一致した時のみ<a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a>を突かれたような挙動をする、ただのパスワード認証のようなhtmlを上げ始めたのです。 結局、「他のチームの問題を解く」という行為はほぼ不可能になり(SHA-256をじっと睨めば解ける方ならちがうかもしれませんが)、もはやディフェンスキーワードの更新を自動化するだけの作業だけが残ったのでした。</p> <p>このゲーム性のなさは、作問者の<a href="https://twitter.com/yagihashoo">Yu Yagihashi</a>氏も認識しており、コンセプトが崩壊したと悲しみの声を表明しておられました。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xd5dabe8)"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a> HELL、開始40分でコンセプト崩壊して無事クソ問 of the Yearの座に輝いた</p>&mdash; コンセプト崩壊太郎 (@yagihashoo) <a href="https://twitter.com/yagihashoo/status/1076745283042631680?ref_src=twsrc%5Etfw">December 23, 2018</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>同時に、どのようにすれば<a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a> HELLがコンセプト崩壊しなかったのか、意見を募集しておられるようですので、なにか思いついた方はつぶやいてみるのもよいのではないでしょうか。</p> <p><blockquote class="twitter-tweet" data-lang="HASH(0xfd65240)"><p lang="ja" dir="ltr"><a class="keyword" href="http://d.hatena.ne.jp/keyword/XSS">XSS</a> HELL、こうすればコンセプト崩壊しなかったのでは!?というコメント、お待ちしてます <a href="https://twitter.com/hashtag/seccon?src=hash&amp;ref_src=twsrc%5Etfw">#seccon</a></p>&mdash; コンセプト崩壊太郎 (@yagihashoo) <a href="https://twitter.com/yagihashoo/status/1076746185409351681?ref_src=twsrc%5Etfw">December 23, 2018</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <h2>宮島</h2> <p>というわけで、松島も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C5%B7%B6%B6%CE%A9">天橋立</a>も終わってしまった今となっては、もう宮島しか我々には残されていないわけです。</p> <p>宮島はどのような問題だったかというと</p> <ul> <li>ある与えられた要件を満たすような動作をする<a class="keyword" href="http://d.hatena.ne.jp/keyword/x86">x86</a><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>のバイナリを作成して投げる</li> <li>テストに合格すれば、フラグがもらえるので、アタックポイントがもらえる</li> <li>バイナリと同時にディフェンスキーワードも送信する <ul> <li>最も短いバイナリを最速でsubmitすることでディフェンスキーワードを書き込むことができる</li> <li>同じ長さのバイナリで2番目以降にsubmitした人はディフェンスキーワードを書き込めない</li> <li>より短いバイナリを他のチームに投げられない限り、書き込まれたディフェンスキーワードのチームにディフェンスポイントが一定時間ごとに入る</li> </ul> </li> </ul> <p>というものでした。</p> <p>画面としては以下のような感じ。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181224/20181224000347.png" alt="f:id:hikalium:20181224000347p:plain" title="f:id:hikalium:20181224000347p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>これは最終問題なので、まあまあな感じですが、最初は</p> <pre class="code" data-lang="" data-unlink>int型の引数a, bが渡されるので、その和を返す関数を実装してください</pre> <p>という感じのかんたんさで、かんたんであるが故にバイナリの短さの限界が見えてしまい、もはや問題予測&amp;早解き大会となっていました。</p> <p>ちなみに、上記のXorはおそらく下記のものが最短かと思われます(他のチームに先を越されてしまいましたが。)</p> <pre class="code" data-lang="" data-unlink>0000000000000000 &lt;func&gt;: 0: 87 ce xchg %ecx,%esi 0000000000000002 &lt;Lcmp&gt;: 2: 30 54 0f ff xor %dl,-0x1(%rdi,%rcx,1) 6: e2 fa loop 2 &lt;Lcmp&gt; 8: c3 retq </pre> <p>LOOP命令を使うのがミソです。SDMを読んでた甲斐がありましたね!</p> <h3>バイナリ早書き支援<a class="keyword" href="http://d.hatena.ne.jp/keyword/Makefile">Makefile</a></h3> <p>最初からバイナリを書いてもいいんですが、間違えやすいので、こんなかんじで最初はcで書き、あとでasmで書いてみて、test.cとリンクしてテストするという感じで作業しました。</p> <pre class="code" data-lang="" data-unlink>c: gcc -Os -c -o c.o c.c cp c.o func.o objdump -d c.o objdump -d c.o | cut -f 3 objcopy -O binary -j .text c.o co od -An -t x1 co asm: as -o asm.o asm.S cp asm.o func.o objdump -d asm.o objdump -d asm.o | cut -f 3 objcopy -O binary -j .text asm.o co od -An -t x1 co test: gcc -o test.bin func.o test.c ./test.bin</pre> <p>まあ、私より周りのプロのほうが早くてあまり役に立てませんでしたが…。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>からバイナリ送信</h3> <p>バイナリ送信がwebフォーム経由だったのですが、ディフェンスキーワードをいれたり、コードをコピペしてEnterを押すのは面倒だったので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/CLI">CLI</a>でできるように準備だけはしました。暇だったので。(だって最速AC取られたら30分後まで勝ち目はないんだもの…)。</p> <pre class="code" data-lang="" data-unlink>const puppeteer = require(&#39;puppeteer&#39;); (async () =&gt; { var key = process.argv[2]; var code = process.argv[3]; const browser = await puppeteer.launch(); const page = await browser.newPage(); page.on(&#39;dialog&#39;, async dialog =&gt; { console.log(dialog.message()); await dialog.dismiss(); }); await page.goto(&#39;http://miyajima.pwn.ja.seccon/&#39;); await page.type(&#39;input&#39;, key); await page.type(&#39;textarea&#39;, code); const elementHandle = await page.$(&#39;button&#39;); await elementHandle.press(&#39;Enter&#39;); const element = await page.$(&#34;.form__attacking-flag&#34;); if(element){ const flag = await page.evaluate(element =&gt; element.value, element); console.log(&#34;FLAG: &#34; + flag); } await page.screenshot({path: &#39;example.png&#39;}); await browser.close(); })();</pre> <p>ぐーぐるくろーむのpuppeteerっていうのを使うと、けっこうお気軽に<a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%A5%D6%A5%E9%A5%A6%A5%B6">Webブラウザ</a>操作の自動化ができておいしいです。べんり。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2FGoogleChrome%2Fpuppeteer" title="GoogleChrome/puppeteer" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/GoogleChrome/puppeteer">github.com</a></cite></p> <p>最初はLighthouseを使おうとしたのですが、どうもうまくいかなかったのでこちらを使いました。 ただ、結構インターネットの海にある使ってみたよ記事は古い<a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>を使っていたりしてうまくいかないことが多かったです。 困った時はちゃんと<a href="https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md">APIドキュメント</a>を見ると楽かもしれません。</p> <h2>感想</h2> <p>少し問題数が少なかったような気がする。特に、アタックポイントにほとんど差がついていなかったと思うので、もう少し問題数を増やすとか、解ききれない難しいものを出してもらえるとよかったかもしれない。 また、問題に穴が多かったというか、ゲーム性が少なく、早押しクイズのような感じになってしまっていた部分が例年より多かったように感じた。</p> <p>とはいえ、解くこと自体は面白かったし、SECCONはSECCONなのでよかったと思います。 来年ももっと進化したSECCONを楽しみにしています!(精進します…。)</p> <p>共に戦った参加者のみなさん、運営のみなさま、関係者の皆様、ありがとうございましたー!</p> hikalium 自作OSでできる!NVDIMMのつかいかた hatenablog://entry/10257846132686154100 2018-12-17T23:47:35+09:00 2018-12-18T20:13:20+09:00 これは、自作OS Advent Calendar 2018 の7番目の素数日の記事です。 はじめに みなさん、NVDIMMって知っていますか?知っている人はぜひ仲良くなりましょうー。 NVDIMMとは、Non-Volatile DIMMの略で、要するにDIMMスロットに刺さる不揮発性の記憶モジュールのことです。 通常のDRAM DIMMは、電源を切るとデータが消えてしまう揮発性の記憶素子なのですが、なんとNVDIMMは電源を切ってもデータが消えません。すごいね! (NVDIMMの実現方法にはいくつか種類があって…という、NVDIMM自体の細かい話はここではしません。) さて、自作OSを書いてい… <p>これは、<a href="https://adventar.org/calendars/2915">自作OS Advent Calendar 2018</a> の7番目の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>日の記事です。</p> <h2>はじめに</h2> <p>みなさん、NVDIMMって知っていますか?知っている人はぜひ仲良くなりましょうー。</p> <p>NVDIMMとは、Non-Volatile DIMMの略で、要するにDIMMスロットに刺さる不揮発性の記憶モジュールのことです。 通常の<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a> DIMMは、電源を切るとデータが消えてしまう揮発性の記憶素子なのですが、なんとNVDIMMは電源を切ってもデータが消えません。すごいね!</p> <p>(NVDIMMの実現方法にはいくつか種類があって…という、NVDIMM自体の細かい話はここではしません。)</p> <p>さて、自作OSを書いている皆様はよくわかると思うのですが、自作OSで何らかのデータを保存するのはとても大変です。メモリにあるデータは電源を切ると消えてしまいますから、HDDや<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSD">SSD</a>やSDカードに書き出さないといけません。そうすると、まずはそれらのデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>のドライバを書かなくてはいけませんし、しかもこれらのデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>はブロック単位でしか書き込みができませんから、何らかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D5%A5%A1%A5%A4%A5%EB%A5%B7%A5%B9%A5%C6%A5%E0">ファイルシステム</a>のような仕組みも用意しなくてはいけません。…大変ですね。</p> <p>そういうわけで、多くのみなさんはデータを保存する機構を実装せず、電源を切ったらデータは全部消えてしまってもいいという割り切りをすることになります。これはかなしい。</p> <p>ところが!NVDIMMはCPUからみたとき、メモリとして認識されるので、ドライバなしにCPUから直接読み書きすることができます。つまり、DIMMに<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%DE%A5%C3%A5%D4%A5%F3%A5%B0">マッピング</a>されたアドレスに書いたデータは、起動後もそのまま読み出せるのです!</p> <p>ということで、この記事では、自作OSでNVDIMMを使うにはどうすればいいかを解説していきます。</p> <h2>検証環境</h2> <p>残念ながら、NVDIMMの実機を個人で買うのはすこしたいへんです。なので、代わりに<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>のNVDIMMエミュレーションを利用することにします。</p> <p>利用したバージョンはコミット<code>7c69b7c849</code>をソースビルドしたものです。</p> <pre class="code" data-lang="" data-unlink>QEMU emulator version 3.0.50 (v3.0.0-1143-g7c69b7c849)</pre> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>オプション</h3> <p>公式ドキュメントは以下にあります。</p> <p><a href="https://github.com/qemu/qemu/blob/master/docs/nvdimm.txt">qemu/docs/nvdimm.txt</a></p> <p>これを参考に、<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>の起動<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%DE%A5%F3%A5%C9%A5%E9%A5%A4%A5%F3">コマンドライン</a>オプションは以下のようにしました。</p> <pre class="code" data-lang="" data-unlink>-bios $(OVMF) \ -machine q35,nvdimm -cpu qemu64 -smp 4 \ -monitor stdio \ -m 8G,slots=2,maxmem=10G \ -drive format=raw,file=fat:rw:mnt -net none \ -object memory-backend-file,id=mem1,share=on,mem-path=pmem.img,size=2G \ -device nvdimm,id=nvdimm1,memdev=mem1</pre> <p>これらのオプションのうち、NVDIMMをエミュレーションする上で重要なポイントは以下の通りです。</p> <ul> <li><code>-machine</code> に <code>nvdimm</code> を追加する。</li> <li><code>-m</code> のサイズは<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>のサイズを設定する。 <ul> <li><code>slots</code> は、(メインの<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>スロット数+NVDIMMスロット数)に設定する。 <ul> <li>(今回の場合 1 + 1 = 2)</li> </ul> </li> <li><code>maxmem</code> は、(メインの<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>容量 + NVDIMMの容量)に設定する。 <ul> <li>(今回の場合 8G + 2G = 10G)</li> </ul> </li> </ul> </li> <li><code>-object</code> と <code>-device</code> の組で、ひとつのファイルバックエンドNVDIMMデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>を作成できる。 <ul> <li><code>-object</code> の<code>id</code> と、<code>-device</code>の<code>memdev</code>の値を一致させる。</li> <li><code>-mem-path</code> には<code>qemu-img</code>で作成したデータイメージのパスを指定する。 <ul> <li>ここでは、<code>qemu-img create pmem.img 2G</code> と実行して作成されたイメージを利用した。</li> </ul> </li> <li><code>-size</code>には、上記データイメージ作成時に渡したパラメータと同じサイズを指定する。</li> </ul> </li> </ul> <p>また、今回は<a class="keyword" href="http://d.hatena.ne.jp/keyword/UEFI">UEFI</a>を利用するため、<code>-bios</code>にはOVMFのコミット<code>b9cee524e6</code>からビルドした<a class="keyword" href="http://d.hatena.ne.jp/keyword/bios">bios</a>イメージを指定しています。</p> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>以外でのエミュレーションができなかった問題</h3> <p>ちなみに、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Linux">Linux</a>以外でNVDIMMエミュレーション(正確にはhostmem-file)が正しく動作しない問題があったので、私がパッチを送っておきました。すでにmasterにはマージされているので、最新の<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>を<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>してご利用ください。</p> <p><a href="https://github.com/qemu/qemu/commit/d5dbde4645fe56a1bcd678f85fa26c5548bcf552">https://github.com/qemu/qemu/commit/d5dbde4645fe56a1bcd678f85fa26c5548bcf552</a></p> <h2>実装の指針</h2> <p>さて、これでエミュレーションの準備は整いました。つぎは実装の計画を立てましょう。</p> <h3>いかにしてNVDIMMのマップされている<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%AA%CD%FD%A5%A2%A5%C9%A5%EC%A5%B9">物理アドレス</a>を取得するか</h3> <p>NVDIMMはメモリバスの配下に接続されているので、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%AA%CD%FD%A5%A2%A5%C9%A5%EC%A5%B9">物理アドレス</a>空間のどこかにNon-volatileなメモリ空間が生い茂っているはずです。 しかし、私たちはそれがどこにあるのかまだ知りません。知るためにはどうすればよいか…ACPIのNFITを読みます。</p> <h4>ACPI NFIT</h4> <p>ACPI Revision 6.0 より、NFITというPlatform Capabilities Structureが追加されました。 NFITとは、<code>NVDIMM Firmware Interface Table</code> の略です。このテーブルを参照することで、実行中のプラットフォーム上にあるNVDIMMの情報を取得できます。</p> <pre class="code" data-lang="" data-unlink>packed_struct ACPI_NFIT { char signature[4]; uint32_t length; uint8_t revision; uint8_t checksum; uint8_t oem_id[6]; uint64_t oem_table_id; uint32_t oem_revision; uint32_t creator_id; uint32_t creator_revision; uint32_t reserved; uint16_t entry[1]; };</pre> <p>今回はそのNFITに含まれる情報の中でも、SPA(System Physical Address) Range Structures に知りたい情報があります。</p> <pre class="code" data-lang="" data-unlink>packed_struct ACPI_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE { uint16_t type; uint16_t length; uint16_t spa_range_structure_index; uint16_t flags; uint32_t reserved; uint32_t proximity_domain; uint64_t address_range_type_guid[2]; uint64_t system_physical_address_range_base; uint64_t system_physical_address_range_length; uint64_t address_range_memory_mapping_attribute; };</pre> <h3>話はわかった。ところで、そのNFITっていうのはどうやったら読めるの?</h3> <p>NFITへのポインタは、ACPIのXSDT(eXtended System Descriptor Table)に格納されています。</p> <pre class="code" data-lang="" data-unlink>packed_struct ACPI_XSDT { char signature[4]; uint32_t length; uint8_t revision; uint8_t checksum; uint8_t oem_id[6]; uint64_t oem_table_id; uint32_t oem_revision; uint32_t creator_id; uint32_t creator_revision; void* entry[1]; };</pre> <p>XSDTへのポインタはRSDT(Root System Description Table)に格納されています。</p> <pre class="code" data-lang="" data-unlink>packed_struct ACPI_RSDT { char signature[8]; uint8_t checksum; uint8_t oem_id[6]; uint8_t revision; uint32_t rsdt_address; uint32_t length; ACPI_XSDT* xsdt; // &lt;&lt;&lt; HERE! uint8_t extended_checksum; uint8_t reserved; };</pre> <p>で、このRSDTへのポインタは…<a class="keyword" href="http://d.hatena.ne.jp/keyword/EFI">EFI</a> Configuration Table にあります。(<a class="keyword" href="http://d.hatena.ne.jp/keyword/EFI">EFI</a>_ACPI_TABLE_GUIDから引ける。)</p> <p>というわけで、実際の順番としては</p> <pre class="code" data-lang="" data-unlink>EFIConfigurationTable -&gt; ACPI_RSDT -&gt; ACPI_XSDT -&gt; ACPI_NFIT -&gt; SPARangeStructure</pre> <p>と辿っていけば、NVDIMMのマップされているアドレス <code>system_physical_address_range_base</code> がわかるわけです。</p> <h2>実装</h2> <p>さあ、これでもうあとは実装するだけですね!</p> <p>ということで、実装してみた例がこちらです。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhikalium%2Fliumos%2Ftree%2F37e4a59f6664b0d719254cfb0a2db9b57324c70b" title="hikalium/liumos" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/hikalium/liumos/tree/37e4a59f6664b0d719254cfb0a2db9b57324c70b">github.com</a></cite></p> <p>軽く実装について説明します。</p> <p>src/liumos.cc の<a href="https://github.com/hikalium/liumos/blob/37e4a59f6664b0d719254cfb0a2db9b57324c70b/src/liumos.cc#L303">MainForBootProcessor()</a>が、起動後に最初に実行される関数です。</p> <p>この関数内の、</p> <pre class="code" data-lang="" data-unlink> ACPI_RSDT* rsdt = static_cast&lt;ACPI_RSDT*&gt;( EFIGetConfigurationTableByUUID(&amp;EFI_ACPITableGUID)); ACPI_XSDT* xsdt = rsdt-&gt;xsdt;</pre> <p>という部分で、EFIConfigurationTableからRSDTを取得し、そこからXSDTを取得しています。</p> <p>そして、以下のようにしてXSDTからNFITを見つけ出し、</p> <pre class="code" data-lang="" data-unlink> ACPI_NFIT* nfit = nullptr; ... for (int i = 0; i &lt; num_of_xsdt_entries; i++) { const char* signature = static_cast&lt;const char*&gt;(xsdt-&gt;entry[i]); if (IsEqualStringWithSize(signature, &#34;NFIT&#34;, 4)) nfit = static_cast&lt;ACPI_NFIT*&gt;(xsdt-&gt;entry[i]); ... }</pre> <p>NFITが存在していれば、適当にSPARange structureを見つけ出して、適宜書き込んだり読み込んだりしてみてその結果を表示しています。</p> <pre class="code" data-lang="" data-unlink> if (nfit) { PutString(&#34;NFIT found\n&#34;); PutStringAndHex(&#34;NFIT Size&#34;, nfit-&gt;length); PutStringAndHex(&#34;First NFIT Structure Type&#34;, nfit-&gt;entry[0]); PutStringAndHex(&#34;First NFIT Structure Size&#34;, nfit-&gt;entry[1]); if (static_cast&lt;ACPI_NFITStructureType&gt;(nfit-&gt;entry[0]) == ACPI_NFITStructureType::kSystemPhysicalAddressRangeStructure) { ACPI_NFIT_SPARange* spa_range = (ACPI_NFIT_SPARange*)&amp;nfit-&gt;entry[0]; PutStringAndHex(&#34;SPARange Base&#34;, spa_range-&gt;system_physical_address_range_base); PutStringAndHex(&#34;SPARange Length&#34;, spa_range-&gt;system_physical_address_range_length); PutStringAndHex(&#34;SPARange Attribute&#34;, spa_range-&gt;address_range_memory_mapping_attribute); PutStringAndHex(&#34;SPARange TypeGUID[0]&#34;, spa_range-&gt;address_range_type_guid[0]); PutStringAndHex(&#34;SPARange TypeGUID[1]&#34;, spa_range-&gt;address_range_type_guid[1]); uint64_t* p = (uint64_t*)spa_range-&gt;system_physical_address_range_base; PutStringAndHex(&#34;\nPointer in PMEM Region: &#34;, p); PutStringAndHex(&#34;PMEM Previous value: &#34;, *p); (*p)++; PutStringAndHex(&#34;PMEM value after write: &#34;, *p); uint64_t* q = reinterpret_cast&lt;uint64_t*&gt;(page_allocator.AllocPages(1)); PutStringAndHex(&#34;\nPointer in DRAM Region: &#34;, q); PutStringAndHex(&#34;DRAM Previous value: &#34;, *q); (*q)++; PutStringAndHex(&#34;DRAM value after write: &#34;, *q); } }</pre> <p>(本当はきちんと見つけ出さなければいけないのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>の場合NFIT中の0番目のエントリに運良くSPARangeStructureがあったので手抜きしています。ごめんなさい!)</p> <p>ね!テーブルをたどるだけの簡単なお仕事でしょ!</p> <h2>実行結果</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EA%A5%DD%A5%B8%A5%C8%A5%EA">リポジトリ</a>のこのハッシュをクローンしてきて<code>make run</code>すると、最初に<code>pmem.img</code>が作成されてから<a class="keyword" href="http://d.hatena.ne.jp/keyword/QEMU">QEMU</a>が起動します。</p> <pre class="code" data-lang="" data-unlink>$ make run make -C src make[1]: Nothing to be done for `default&#39;. qemu-img create pmem.img 2G Formatting &#39;pmem.img&#39;, fmt=raw size=2147483648 mkdir -p mnt/EFI/BOOT cp src/BOOTX64.EFI mnt/EFI/BOOT/ qemu-system-x86_64 -bios ovmf/bios64.bin -machine q35,nvdimm -cpu qemu64 -smp 4 -monitor stdio -m 8G,slots=2,maxmem=10G -drive format=raw,file=fat:rw:mnt -net none -object memory-backend-file,id=mem1,share=on,mem-path=pmem.img,size=2G -device nvdimm,id=nvdimm1,memdev=mem1 QEMU 3.0.50 monitor - type &#39;help&#39; for more information (qemu)</pre> <p>画面としてはこのような感じになります。</p> <p><figure class="figure-image figure-image-fotolife" title="最初の起動"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181217/20181217181025.png" alt="f:id:hikalium:20181217181025p:plain" title="f:id:hikalium:20181217181025p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>最初の起動</figcaption></figure></p> <p>今回は比較のため、PMEM領域に含まれるアドレスと、<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>領域に含まれるアドレスにある8バイト整数を起動毎にそれぞれインクリメントしていくように実装しました。</p> <p>ひとまず最初は、どちらも運良く0で初期化されていたので、それぞれインクリメントしたら1になっていますね。</p> <p>では、<a class="keyword" href="http://d.hatena.ne.jp/keyword/qemu">qemu</a>のコンソールに<code>q</code>と打ち込んで終了させ、もう一度<code>make run</code>してみましょう。</p> <p>すると…!</p> <p><figure class="figure-image figure-image-fotolife" title="2回目の起動"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181217/20181217231241.png" alt="f:id:hikalium:20181217231241p:plain" title="f:id:hikalium:20181217231241p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>2回目の起動</figcaption></figure></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>とPMEM、どちらも最初の起動時と同じポインタを読み書きしているのですが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>では最初の起動時にインクリメントした1は忘れ去られてまた0からやりなおしになっている一方、PMEMでは前回のインクリメント結果である1が再起動後も残っていて、今度は2が書き込まれました!</p> <p>念の為もう一回再起動してみると…</p> <p><figure class="figure-image figure-image-fotolife" title="3回目の起動"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181217/20181217231640.png" alt="f:id:hikalium:20181217231640p:plain" title="f:id:hikalium:20181217231640p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>3回目の起動</figcaption></figure></p> <p>やっぱり<a class="keyword" href="http://d.hatena.ne.jp/keyword/DRAM">DRAM</a>はデータが消えてしまっていますが、PMEMは残っていますね!すごい!</p> <h2>まとめ</h2> <p>というわけで、NVDIMMを使えば、自作OSでも簡単にデータを保存して再起動後にも残しておけるということがわかりました! とはいえ今回は簡単な説明しかしておらず、実装は手抜きですし、キャッシュをフラッシュしなければデータが消える可能性があるなど、細かい点で注意しなければならないことが山積みです。</p> <p>これらを考慮しつつ、liumOSはNVDIMMを有効活用した新しいOSを目指して開発をしてゆきますので、今後にご期待ください!</p> <p>では皆様、よいOS自作ライフを!</p> <h2>参考文献</h2> <ul> <li><a href="https://pmem.io/documents/NVDIMM_Namespace_Spec.pdf">NVDIMM Namespace Specification Rev. 1.0</a></li> <li><a href="http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf">ACPI Specification Version 6.2 Errata A</a></li> <li><a href="http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_7_A%20Sept%206.pdf">UEFI Specification Version 2.7 (Errata A)</a></li> </ul> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/%CA%D4%BD%B8%CD%FA%CE%F2">編集履歴</a></h2> <ul> <li>ACPI Specおよび<a class="keyword" href="http://d.hatena.ne.jp/keyword/UEFI">UEFI</a> Specについて、最新バージョンを参照するよう参考文献を変更しました。</li> <li>ACPI SpecにNFITが追加されたのは6.2Aではなく6.0からとの指摘を受けましたので、該当箇所を修正しました。 <ul> <li>Thank you, <a href="https://twitter.com/YasunoriGoto1/status/1074978459561029632">@YasunoriGoto1</a>!</li> </ul> </li> </ul> hikalium compilium v2 (in progress)の工夫点 hatenablog://entry/10257846132681504509 2018-12-07T21:06:46+09:00 2018-12-07T21:06:46+09:00 この記事は、言語実装アドベントカレンダーの7日目にあたります。 ちなみに、これを書いている現在は2018年12月7日の12:00です。果たして今日中に記事を公開することはできるのでしょうか…。 compilium v2とは github.com compiliumは、hikaliumが開発しているC11準拠(予定)のCコンパイラです。C言語で書かれています。 compilium v2では、v1での反省点およびセキュリティ・キャンプ全国大会2018のCコンパイラ自作ゼミでの知見をもとに、よりわかりやすく単純でインクリメンタルに開発できることを目標に開発しています。 この記事では、これらの得られた… <p>この記事は、<a href="https://qiita.com/advent-calendar/2018/lang_dev">言語実装アドベントカレンダー</a>の7日目にあたります。</p> <p>ちなみに、これを書いている現在は2018年12月7日の12:00です。果たして今日中に記事を公開することはできるのでしょうか…。</p> <h2>compilium v2とは</h2> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fhikalium%2Fcompilium" title="hikalium/compilium" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/hikalium/compilium">github.com</a></cite></p> <p>compiliumは、hikaliumが開発しているC11準拠(予定)のC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>です。<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>で書かれています。</p> <p>compilium v2では、v1での反省点およびセキュリティ・キャンプ全国大会2018のC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>自作ゼミでの知見をもとに、よりわかりやすく単純でインクリメンタルに開発できることを目標に開発しています。</p> <p>この記事では、これらの得られた知見とともに、それらが実際にどのようにcompilium v2に活かされているかを紹介します。</p> <h2>最初から<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>マシンとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>を出力する</h2> <p>当初、C<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミでは、スタックマシンとして<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>を出力するよう受講者のみなさんにお願いしていました。</p> <p>これは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>割り当てを最初から考慮するのは大変であり、スタックマシンならばシンプルに実装できるという予想に基づいたものでした。</p> <p>実際、スタックマシンを採用したことで、式のコード生成については、かなりスムーズに習得してもらうことができました。</p> <p>一方で、スタックマシンの弱点としては、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>レベルでの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%D0%A5%C3%A5%B0">デバッグ</a>が非常に困難になることが挙げられます。 これは、出力の多くが本質的な計算ではなくpush/popに占められることと、各計算の間で値がどのように伝播するかわかりづらいことが原因でした。</p> <p>そこで、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>マシンの可能性を再考してみたところ、式に閉じた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>マシンであれば、複雑な式を与えない限り、<a href="https://github.com/hikalium/compilium/blob/7a408a03e2ed8bcac62ee930bd210089979dcbfa/compilium.c#L987-L1318">単純なコード</a>でもうまく生成でき、出力も自然に近い<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>になることがわかりました。</p> <h3>簡単な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>マシンの実装</h3> <p>式(Expression)に閉じた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>マシン、つまり、異なる式の間で値を引き継いだりしないようなものは容易に実装することができます。 具体的には、値であれば新しく<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>を確保し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>であればその各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%DA%A5%E9%A5%F3%A5%C9">オペランド</a>に対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>割り当てを実行したのち、戻り値を戻すための<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>一つをのぞいてすべて解放する、という手順を行えばよいです。</p> <p>戻り値を戻すための<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>として、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の左側の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%DA%A5%E9%A5%F3%A5%C9">オペランド</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>を利用することにした場合、<code>2 + 3 * 5</code>は、下の図のように割り当てることができます(R, G, Bはそれぞれ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>名です)。 <figure class="figure-image figure-image-fotolife" title="レジスタ割り当てのようす"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181207/20181207192720.gif" alt="f:id:hikalium:20181207192720g:plain" title="f:id:hikalium:20181207192720g:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>割り当てのようす</figcaption></figure></p> <p>実際には、この式は2つの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>で計算可能な式(3*5を先に計算すればよい)なのですが、そんなことは気にしたら負けです。 とにかく単純に実装することがcompiliumの目的ですからね!</p> <h3>利用可能な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a></h3> <p>SystemV ABI において、保存せずに破壊しても問題ない汎用<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>は、以下のものになります。</p> <pre class="code" data-lang="" data-unlink>rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11</pre> <p>このうち、</p> <ul> <li>raxは戻り値の格納に使われる</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/rdx">rdx</a>はmul, div系で変更される可能性がある(MUL r/m64: <a class="keyword" href="http://d.hatena.ne.jp/keyword/RDX">RDX</a>:RAX ← RAX ∗ r/m64))</li> <li>rcxはシフト系演算で<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A5%DA%A5%E9%A5%F3%A5%C9">オペランド</a>として利用される(シフト系演算のシフト量は、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>で指定する場合CLしか使えない)</li> </ul> <p>ことから、単純のため利用しないことにすると、気軽に自由に使える<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>は</p> <pre class="code" data-lang="" data-unlink>rsi, rdi, r8, r9, r10, r11</pre> <p>の6つになります。</p> <h3>なぜこれで大体うまくいくのか</h3> <p><figure class="figure-image figure-image-fotolife" title="レジスタ割り当ての例"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181207/20181207200845.png" alt="f:id:hikalium:20181207200845p:plain" title="f:id:hikalium:20181207200845p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>割り当ての例</figcaption></figure></p> <p>上の図を参照してもらえればわかるように、ASTが右に伸びるほど、必要な<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>の個数が増えていることがわかります。</p> <p>ASTが右に伸びるということは、右側のほうを先に計算する必要がある、つまり、右側の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>の優先順位が高いか、同じ優先順位でも右結合の場合か、もしくはかっこで包まれている場合に限られます。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%B8%C0%B8%EC">C言語</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%F3%B9%E0%B1%E9%BB%BB%BB%D2">二項演算子</a>で右結合性のものはassignment-operatorのみであり、これを連続して使うような場合はあまり多くありません。</p> <p>したがって、優先順位の異なる<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>や括弧をひとつの式の中で多用しないかぎり、この<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>でも大体うまくいくわけです。</p> <p>うまくいかなかったらどうするかって?ソースを書き換えちゃいましょう!変数を使えばどんな式も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>できる形に確実に書き直せますよ!</p> <h2>エラーメッセージの改善</h2> <p>compilium v1では、エラー時にその行番号を報告することしかできませんでした。 しかし、式のテストは1行にソースが押し込められてしまうことから、行番号は大して役にたちませんでした。 そこで、compilium v2では、エラー発生時に該当<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ンの前後を表示できるように実装されました。</p> <pre class="code" data-lang="" data-unlink>{int *a; return sizeof(a);} ^^^^^^ Error: Generate: Not implemented unary prefix op</pre> <h2>assignment-expression のパーストリック</h2> <pre class="code" data-lang="" data-unlink>assignment-expression: conditional-expression unary-expression assignment-operator assignment-expression</pre> <p>assignment-expressionが右<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>であることは先ほど触れましたが、右<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>とはいっても単純な右<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>ではありません。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>の終端点では conditional-expression が許されるのに対し、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BA%C6%B5%A2">再帰</a>途中の左辺には unary-expressionしか許されません。 パーサを書いていて、ここをどう処理するか悩んでいるみなさんも多いのではないでしょうか。(もしかしてみんな悩まない!?)</p> <p>compilium v2の実装にあたり、この問題の解決策をいくつか考えてみました。</p> <h3>方法1: unary-expressionを先読みする</h3> <p>conditional-expressionは、cast-expressionの場合を除いて、先頭にunary-expressionがくる。</p> <p>そして、cast-expressionの場合に左側に来る要素はunary-expressionとして認識される可能性がない<code>( type-name )</code> ので、unary-expressionを先読みして直後にassignment-operatorがくるか調べ、来なければそのunary-expressionを渡しつつconditional-expressionをパースすれば良い。</p> <ul> <li>利点: <ul> <li>文法に沿ったパース結果を得られる</li> </ul> </li> <li>欠点: <ul> <li>パーサの一部のみ引数が増える</li> </ul> </li> </ul> <h3>方法2: 試してみてだめだったら巻き戻す</h3> <p><a href="https://github.com/hikalium/compilium/blob/529e8935fc28cc91b4caab8c9f145bd2dc973882/parser.c#L316">compilium v1</a>で採用していた方法</p> <ul> <li>利点 <ul> <li>文法に沿ったパース結果を得られる</li> </ul> </li> <li>欠点 <ul> <li>巻き戻すのはださい(このためだけにTokenStreamの位置を保存しなければいけない)</li> <li>効率が悪い(2回同じことをすることになる可能性がある)</li> </ul> </li> </ul> <h3>方法3: conditional-expressionとして読んでから、読んだ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C8%A1%BC%A5%AF">トーク</a>ンのクラスを判定する</h3> <ul> <li>利点: <ul> <li>文法に沿ったパース結果を得られる</li> <li>パーサの引数の数を統一できる</li> </ul> </li> <li>欠点: <ul> <li>ASTのタイプを注意深く設計しなければならない</li> <li>unary-expression以下のASTタイプを新たに実装した際に判定条件に追加しなければならない <ul> <li>unary-expression, <a class="keyword" href="http://d.hatena.ne.jp/keyword/postfix">postfix</a>-expression, primary-expression がunary-expressionに含まれる。</li> </ul> </li> </ul> </li> </ul> <h3>方法4: 単純な右再起になるよう構文を変更してしまう</h3> <pre class="code" data-lang="" data-unlink>assignment-expression: conditional-expression conditional-expression assignment-operator assignment-expression ^^^^^^^^^^^^^^^^^^^^^^</pre> <p><a href="https://www.sigbus.info/compilerbook/#%E3%83%91%E3%83%BC%E3%82%B5%E3%81%AE%E5%A4%89%E6%9B%B4">9ccで採用</a>されている方法 <a href="https://github.com/hikalium/compilium/blob/7a408a03e2ed8bcac62ee930bd210089979dcbfa/compilium.c#L839">compilium v2でもこれを採用</a>することにした。</p> <ul> <li>利点: <ul> <li>パーサの記述が楽</li> </ul> </li> <li>欠点: <ul> <li>構文にあてはまらない入力をパースできてしまう <ul> <li><code>a+1 = 2</code> のような構文は本来パースできない</li> </ul> </li> <li>ただし意味解析で除去できる(左辺がlvalueかどうかチェックすればよい)</li> <li>副作用として、条件<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B1%E9%BB%BB%BB%D2">演算子</a>を左辺値として用いることができるようになる。 <ul> <li>これは<a href="https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Lvalues.html">gcc拡張</a>である</li> <li>しかもこの構文は<a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a>ではvalid(つまりこっちのほうが自然)</li> </ul> </li> </ul> </li> </ul> <p>というわけで、皆さんも方法4を採用するといいと思います!(楽なので)</p> <h2>主要な構造体をTokenとASTNodeのみに集約</h2> <p>compilium v1 では、型がついていないと不安だし、メモリを効率よく使いたいという思いから、<a href="https://github.com/hikalium/compilium/blob/529e8935fc28cc91b4caab8c9f145bd2dc973882/compilium.h#L161-L359">ASTの各タイプごとに構造体を用意</a>していました。</p> <p>しかし、これは機能追加ごとのコード量が増大する要因となり、またほぼ同一内容のコードがソース中に増える原因となりました。</p> <p>compilium v2 では、思い切ってASTおよび型情報を<a href="https://github.com/hikalium/compilium/blob/7a408a03e2ed8bcac62ee930bd210089979dcbfa/compilium.c#L383">単一の構造体ASTNode</a>に押し込めることにしました。</p> <p>これは、メモリ効率の低下を招きますが、まあ昨今みんなRAMは32GB以上積んでいると思われますので問題ないでしょう…。</p> <p>(やっぱり無理して書くよりも気楽に書いた方がいいですよ。)</p> <h2>おわりに</h2> <p>本来はもっと真面目にもっと詳細に語りたかったのですが、ちょっと疲れてしまってゆるふわになってしまいました。ごめんなさい…。</p> <p>特に型の話についてはもう少し語りたいので、12/23の<a href="https://qiita.com/advent-calendar/2018/c_lang">C言語アドベントカレンダー</a>でまた書きたいと思います。</p> <p>私も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>初心者なので、何か指摘や質問等あればぜひ<a href="https://twitter.com/hikalium">Twitter</a>のほうまでお願いします!</p> <p>年内にはv2がセルフホストできるようにがんばりますので、どうか生暖かい目で見守っていてください…。</p> <p>今年度<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BB%A5%AD%A5%E5%A5%EA%A5%C6%A5%A3%A5%AD%A5%E3%A5%F3%A5%D7">セキュリティキャンプ</a>2018のC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>ゼミに参加してくださったみなさん、そして一緒に講師を担当していただいたRuiさんには、実装方法など様々な面でよい刺激をいただきました。ありがとうございます。</p> <p>ということで、</p> <p><span style="font-size: 200%">みなさんもC<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9">コンパイラ</a>書きましょうね?</span></p> <p>楽しいぞ!</p> <h2>参考文献</h2> <ul> <li><a href="https://www.sigbus.info/compilerbook">低レイヤを知りたい人のためのCコンパイラ作成入門 - Rui Ueyama</a> <ul> <li>寄付は<a href="https://compilerbook.booth.pm/items/1077279">こちら</a>からどうぞ!</li> </ul> </li> <li><a href="http://www.iso-9899.info/n1570.html">ISO/IEC 9899:201x Committee Draft April 12, 2011 N1570</a></li> <li><a href="https://www.uclibc.org/docs/psABI-x86_64.pdf">System V Application Binary Interface AMD64 Architecture Processor Supplement Draft Version 0.99.7</a></li> <li><a href="https://software.intel.com/en-us/articles/intel-sdm">Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2 (2A, 2B, 2C &amp; 2D): Instruction Set Reference, A-Z</a></li> </ul> hikalium SECCON 2018 Online CTF Writeup hatenablog://entry/10257846132660966109 2018-10-28T16:48:12+09:00 2018-10-28T17:11:46+09:00 https://score-quals.seccon.jp/team/115 チーム Bluemermaid として参加しました。総合17位、国内6位だったようです。 私がsubmitしたフラグは1つでした。(2つ解けたのだけど、1つは少し前に他の方が解いていた…。はやい。) 解けた問題 Special Device File 毎度おなじみ謎アーキでした。 $ file runme_8a10b7425cea81a043db0fd352c82a370a2d3373 runme_8a10b7425cea81a043db0fd352c82a370a2d3373: ELF 64-bit LSB exe… <p><a href="https://score-quals.seccon.jp/team/115">https://score-quals.seccon.jp/team/115</a></p> <p>チーム Bluemermaid として参加しました。総合17位、国内6位だったようです。 私がsubmitしたフラグは1つでした。(2つ解けたのだけど、1つは少し前に他の方が解いていた…。はやい。)</p> <h1>解けた問題</h1> <h2>Special Device File</h2> <p>毎度おなじみ謎アーキでした。</p> <pre class="code" data-lang="" data-unlink>$ file runme_8a10b7425cea81a043db0fd352c82a370a2d3373 runme_8a10b7425cea81a043db0fd352c82a370a2d3373: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped</pre> <p>と言ってもaarch64ですが。</p> <p>まずは毎度おなじみ環境構築をします。私は<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a> 18.04でやりました。(事前にやっておけ。) 全部のアーキをビルドしていると試合が終わってしまうので、必要なアーキだけtargets.shに書いておくとよいでしょう。</p> <p>そんなわけで、とりあえずシミュレータで実行してみると</p> <pre class="code" data-lang="" data-unlink>/usr/local/cross2-gcc494/bin/aarch64-elf-run runme_8a10b7425cea81a043db0fd352c82a370a2d3373 </pre> <p>トラップで落ちます。まあきっと未実装なのでしょう。</p> <p>みんな大好きobjdumpをみてみると、</p> <pre class="code" data-lang="" data-unlink>000000000000140c &lt;__exit&gt;: 140c: d4200000 .word 0xd4200000 1410: d65f03c0 ret 0000000000001414 &lt;__read&gt;: 1414: d28000c8 mov x8, #0x6 // #6 1418: d45e0000 .word 0xd45e0000 141c: d65f03c0 ret 0000000000001420 &lt;__write&gt;: 1420: d28000a8 mov x8, #0x5 // #5 1424: d45e0000 .word 0xd45e0000 1428: d65f03c0 ret 000000000000142c &lt;__open&gt;: 142c: d2800028 mov x8, #0x1 // #1 1430: d45e0000 .word 0xd45e0000 1434: d65f03c0 ret 0000000000001438 &lt;__close&gt;: 1438: d2800048 mov x8, #0x2 // #2 143c: d45e0000 .word 0xd45e0000 1440: d65f03c0 ret 1444: d503201f nop 1448: d503201f nop </pre> <p>こんな感じでたいへん怪しいです。きっと0xd45e0000という命令を実装しないといけないのでしょう。</p> <p>ここで、シミュレータをトレース付きで実行してみると、</p> <pre class="code" data-lang="" data-unlink>/usr/local/cross-gcc494/aarch64-elf/bin/run --trace-syscall=on runme_8a10b7425cea81a043db0fd352c82a370a2d3373 </pre> <p>どこでこけているのかわかるようになります。</p> <p>具体的には、<code>cross-gcc494/toolchain/gdb-7.12.1/sim/aarch64/simulator.c</code>の中の<code>handle_halt</code>関数内です。(このソースは1万5000行くらいあって、ファイル分けてほしかったなあという気持ちになった。)</p> <pre class="code" data-lang="" data-unlink>static void handle_halt (sim_cpu *cpu, uint32_t val) { .... switch (aarch64_get_reg_u32 (cpu, 0, NO_SP)) { case AngelSVC_Reason_HeapInfo: ... case AngelSVC_Reason_Rename: case AngelSVC_Reason_Elapsed: default: TRACE_SYSCALL (cpu, &#34; HLT [Unknown angel %x]&#34;, aarch64_get_reg_u32 (cpu, 0, NO_SP)); sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), sim_stopped, SIM_SIGTRAP); } aarch64_set_reg_u64 (cpu, 0, NO_SP, result); } </pre> <p>この関数の下方、AngelSVC_XXXでswitch-caseのdefaultで落ちていました。ということで、適当にここにハンドラを作ってあげればよさそうです。</p> <p>syscall番号は、先のobjdump disasより、x8<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>に代入されていることがわかっているので、引数は<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%B8%A5%B9%A5%BF">レジスタ</a>0から入ると仮定していろいろみてみたところ、なんと<code>/dev/xorshift64</code>といういかにもなデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>をopenしていることがわかりました。 最初のwriteはシードを設定するのでしょう。そして、後続のreadで乱数を取得すると予想できます。 というわけで、こんな感じで書いてみるとよさそうです。</p> <pre class="code" data-lang="" data-unlink> default: { static uint64_t seed = 0; uint64_t syscall_id = aarch64_get_reg_u64 (cpu, 8, SP_OK); if(syscall_id == 1) { uint64_t pathname = aarch64_get_reg_u64 (cpu, 0, SP_OK); uint64_t flags = aarch64_get_reg_u64 (cpu, 1, SP_OK); uint64_t mode = aarch64_get_reg_u64 (cpu, 1, SP_OK); printf(&#34;open \n&#34;); printf(&#34;pathname:%s \n&#34;, aarch64_get_mem_ptr (cpu, pathname)); break; } else if(syscall_id == 2) { printf(&#34;close\n&#34;); break; } else if(syscall_id == 5) { printf(&#34;write\n&#34;); uint64_t buf = aarch64_get_reg_u64 (cpu, 1, SP_OK); uint64_t size = aarch64_get_reg_u64 (cpu, 2, SP_OK); printf(&#34;buf:%lX \n&#34;, buf); printf(&#34;size:%lX \n&#34;, size); seed = aarch64_get_mem_u64 (cpu, buf); printf(&#34;seed:%lX \n&#34;, seed); break; } else if(syscall_id == 6) { uint64_t buf = aarch64_get_reg_u64 (cpu, 1, SP_OK); uint64_t size = aarch64_get_reg_u64 (cpu, 2, SP_OK); printf(&#34;read\n&#34;); printf(&#34;seed:%lX \n&#34;, seed); printf(&#34;buf:%lX \n&#34;, buf); printf(&#34;size:%lX \n&#34;, size); aarch64_set_mem_u64(cpu, buf, xorshift64_2(&amp;seed)); printf(&#34;seed:%lX \n&#34;, seed); break; } printf(&#34;not implemented syscall %lX\n&#34;, syscall_id); } TRACE_SYSCALL (cpu, &#34; HLT [Unknown angel %x]&#34;, aarch64_get_reg_u32 (cpu, 0, NO_SP)); sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), sim_stopped, SIM_SIGTRAP);</pre> <p>注意しておきたいのは、readは戻り値ではなく、メモリに読み込んだ値を書き込んで返すということです。当たり前なのですが、私はうっかり戻り値に収まる大きさだったので戻り値として乱数を返してしまっており、時間を少し無駄にしました。(そのぶんaarch64の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%BB%A5%F3%A5%D6%A5%EA">アセンブリ</a>を読めるようになったのでよしとしよう)。</p> <p>ちなみに<code>xorshift64_2</code>は、試行錯誤の結果以下のコードでうまくいきました。(試行錯誤の過程が関数名に現れている。)</p> <pre class="code" data-lang="" data-unlink>uint64_t xorshift64_2(uint64_t *state) { uint64_t x = *state; x = x ^ (x &lt;&lt; 13); x = x ^ (x &gt;&gt; 7); x = x ^ (x &lt;&lt; 17); *state = x; return x; }</pre> <p>xorshiftは、よい周期性をもつシフトパラメータがいくつも存在するので、どれが選ばれるかは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BC%C2%C1%F5%B0%CD%C2%B8">実装依存</a>なのですが、このパラメータはxorshiftの論文内で例として用いられていたものでした。</p> <p><a href="https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf">Xorshift RNGs George Marsaglia ∗The Florida State University</a></p> <p>余談ですが、論文内のxorshift32の実装例のところに</p> <blockquote><p>It uses one of my favorite choices, [a, b, c] = [13, 17, 5]</p></blockquote> <p>と書いてあって、めっちゃわかるー、ってなっていました。64bit版もきれいでよい。</p> <p>まあ、こんな感じでデ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%A4%A5%B9">バイス</a>の実装自体は終わりですが、文字出力のほうも既存のsyscallの実装にかぶっていたのでよしなにしてあげます。(同関数の上方です。)</p> <pre class="code" data-lang="" data-unlink> case AngelSVC_Reason_Open: { /* Get the pointer */ /* uint64_t ptr = aarch64_get_reg_u64 (cpu, 1, SP_OK);. */ /* FIXME: For now we just assume that we will only be asked to open the standard file descriptors. */ static int fd = 0; result = fd ++; //TRACE_SYSCALL (cpu, &#34; AngelSVC: Open file %d&#34;, fd - 1); uint64_t p0 = aarch64_get_reg_u64 (cpu, 0, SP_OK); uint64_t p1 = aarch64_get_reg_u64 (cpu, 1, SP_OK); uint64_t p2 = aarch64_get_reg_u64 (cpu, 2, SP_OK); uint64_t p19 = aarch64_get_reg_u64 (cpu, 19, SP_OK); //printf(&#34;p0:%lx p1:%lx p2:%lx sp:%lx p19:%lx\n&#34;, p0, p1, p2, aarch64_get_reg_u64 (cpu, 31, SP_OK), p19); printf (&#34;%c&#34;, aarch64_get_mem_u8(cpu, p1)); } break;</pre> <p>(いろいろdeadcodeがありますが気にしないでください。)</p> <p>これでシミュレータを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a>して再度実行してあげるとフラグを得られました。</p> <p><code>SECCON{UseTheSpecialDeviceFile}</code></p> <h2>Special Instructions</h2> <p>これも謎アーキです。cross-<a class="keyword" href="http://d.hatena.ne.jp/keyword/gcc">gcc</a>のサンプルをfileしたときの出力と、与えられたファイルのfileを比較した結果、アーキはmoxieとわかりました。</p> <pre class="code" data-lang="" data-unlink>$ file runme_f3abe874e1d795ffb6a3eed7898ddcbcd929b7be runme_f3abe874e1d795ffb6a3eed7898ddcbcd929b7be: ELF 32-bit MSB executable, *unknown arch 0xdf* version 1 (SYSV), statically linked, not stripped</pre> <p><code>*unknown arch 0xdf*</code> いい響きだ。</p> <p>さて、というわけで適当に実行してみると、</p> <pre class="code" data-lang="" data-unlink>This program uses special instructions. SETRSEED: (Opcode:0x16) RegA -&gt; SEED GETRAND: (Opcode:0x17) xorshift32(SEED) -&gt; SEED SEED -&gt; RegA</pre> <p>と出てから、SIGILLで落ちてしまいます。</p> <p><code>cross-gcc494/toolchain/gdb-7.12.1/sim/moxie/interp.c</code> にソースがあるので適当に読むと、該当する命令番号にご丁寧にも<code>/*bad*/</code>と書かれているのがわかりました。というわけで、適当に実装しちゃいましょう。</p> <pre class="code" data-lang="" data-unlink> case 0x16: /* bad */ { int a = (inst &gt;&gt; 4) &amp; 0xf; xorstate = cpu.asregs.regs[a]; //printf(&#34;SETRSEED(%X)\n&#34;, xorstate); } break; case 0x17: /* bad */ { int a = (inst &gt;&gt; 4) &amp; 0xf; //printf(&#34;GETRAND SEED=%X\n&#34;, xorstate); cpu.asregs.regs[a] = XorShift(&amp;xorstate); } break;</pre> <p>変数 <code>xorstate</code> は適当に関数<code>sim_engine_run</code>の先頭でstatic宣言しておきます。</p> <pre class="code" data-lang="" data-unlink>void sim_engine_run (SIM_DESC sd, int next_cpu_nr, /* ignore */ int nr_cpus, /* ignore */ int siggnal) /* ignore */ { word pc, opc; unsigned short inst; sim_cpu *scpu = STATE_CPU (sd, 0); /* FIXME */ address_word cia = CPU_PC_GET (scpu); static int xorstate = 0;</pre> <p>で、問題はxorshiftです。論文で示されているパラメータは64セットあるのですが、十数個試しても引っかかりません。こまった。</p> <p>というわけで、適当にパラメタ化してソルバを書いてやりました。</p> <pre class="code" data-lang="" data-unlink>int shift_table[9 * 9 * 3] = { 1, 3,10, 1, 5,16, 1, 5,19, 1, 9,29, 1,11, 6, 1,11,16, 1,19, 3, 1,21,20, 1,27,27, 2, 5,15, 2, 5,21, 2, 7, 7, 2, 7, 9, 2, 7,25, 2, 9,15, 2,15,17, 2,15,25, 2,21, 9, 3, 1,14, 3, 3,26, 3, 3,28, 3, 3,29, 3, 5,20, 3, 5,22, 3, 5,25, 3, 7,29, 3,13, 7, 3,23,25, 3,25,24, 3,27,11, 4, 3,17, 4, 3,27, 4, 5,15, 5, 3,21, 5, 7,22, 5, 9,7 , 5, 9,28, 5, 9,31, 5,13, 6, 5,15,17, 5,17,13, 5,21,12, 5,27, 8, 5,27,21, 5,27,25, 5,27,28, 6, 1,11, 6, 3,17, 6,17, 9, 6,21, 7, 6,21,13, 7, 1, 9, 7, 1,18, 7, 1,25, 7,13,25, 7,17,21, 7,25,12, 7,25,20, 8, 7,23, 8,9,23 , 9, 5,1 , 9, 5,25, 9,11,19, 9,21,16,10, 9,21,10, 9,25,11, 7,12,11, 7,16,11,17,13,11,21,13,12, 9,23,13, 3,17, 13, 3,27,13, 5,19,13,17,15,14, 1,15,14,13,15,15, 1,29,17,15,20,17,15,23,17,15,26, }; uint32_t XorShift(uint32_t *state) { *state ^= *state &lt;&lt; shift_table[SHIFT_INDEX * 3 + 0]; *state ^= *state &gt;&gt; shift_table[SHIFT_INDEX * 3 + 1]; *state ^= *state &lt;&lt; shift_table[SHIFT_INDEX * 3 + 2]; return *state; }</pre> <p>SHIFT_INDEXを定義してビルド&amp;実行をぶん回す<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8">スクリプト</a>を用意して</p> <pre class="code" data-lang="" data-unlink>for i in {0..80} do echo index=$i touch ~/repo/cross-gcc494/toolchain/gdb-7.12.1/sim/moxie/interp.c &amp;&amp; \ make -s -C ~/repo/cross-gcc494/build/gdb/moxie-elf/sim CFLAGS+=&#34;-DSHIFT_INDEX=$i &#34; &amp;&gt; /dev/null &amp;&amp; \ cp ~/repo/cross-gcc494/build/gdb/moxie-elf/sim/moxie/run /usr/local/cross-gcc494/moxie-elf/bin/ &amp;&amp; \ /usr/local/cross-gcc494/moxie-elf/bin/run runme_f3abe874e1d795ffb6a3eed7898ddcbcd929b7be | grep SECCON &amp;&amp; exit done</pre> <p>実行すると</p> <pre class="code" data-lang="" data-unlink>$ ./solve.sh index=0 ... index=74 SECCON{MakeSpecialInstructions}</pre> <p>74番目は...<code>13,17,15</code>でしたね。うつくしい…。</p> <p>ということで、フラグを得ました。(ところが十数分前にsrupさんがsubmitしていたのでした。きっとソルバを書き始めようとしていた頃でしょう。ちょっとくやしい。)</p> <h1>解けなかった問題</h1> <h2>q-escape</h2> <p>megumishさんから教えていただいた</p> <ul> <li><a href="https://ntddk.github.io/2018/05/14/def-con-ctf-qualifier-2018-round-up/">https://ntddk.github.io/2018/05/14/def-con-ctf-qualifier-2018-round-up/</a></li> <li><a href="https://kitctf.de/writeups/hitb2017/babyqemu">https://kitctf.de/writeups/hitb2017/babyqemu</a></li> <li><a href="https://blog.eadom.net/writeups/qemu-escape-vm-escape-from-0ctf-2017-finals-writeup/">https://blog.eadom.net/writeups/qemu-escape-vm-escape-from-0ctf-2017-finals-writeup/</a></li> </ul> <p>あたりを参考にしつつ、情報収拾をしている段階で時間切れでした。</p> <pre class="code" data-lang="" data-unlink>$ ./qemu-system-x86_64 -device help 2&gt;&amp;1 | grep cydf name &#34;cydf-vga&#34;, bus PCI, desc &#34;Cydf CLGD 54xx VGA&#34; name &#34;isa-cydf-vga&#34;, bus ISA</pre> <pre class="code" data-lang="" data-unlink>$ nm qemu-system-x86_64 | grep cydf | grep &#39; d &#39; 0000000000f5a580 d isa_cydf_vga_properties 0000000000f5a460 d pci_vga_cydf_properties</pre> <pre class="code" data-lang="" data-unlink>$ nm qemu-system-x86_64 | grep mmio | grep cydf 000000000068da40 t cydf_mmio_blt_read 000000000068ec70 t cydf_mmio_blt_write 0000000000a99bc0 r cydf_mmio_io_ops 000000000068dd90 t cydf_mmio_read 000000000068f9f0 t cydf_mmio_write</pre> <pre class="code" data-lang="" data-unlink>00:02.0 Class 0300: 1234:1111</pre> <pre class="code" data-lang="" data-unlink>/ # cat /proc/iomem | grep 00:02.0 fc000000-fcffffff : 0000:00:02.0 febc0000-febc0fff : 0000:00:02.0</pre> <p>これはがんばれば解けそうな気がするのでぜひやりたい。</p> <h2>Needle in a haystack</h2> <p>場所の特定はした。大阪の梅田ですね。(「新梅田研修センター」という看板が目立っていた。) 画面中央のビルは実在しなさそうなので怪しかったのですが、動画処理は得意ではないので撤退しました。</p> <h1>まとめ</h1> <p>今回は謎アーキ問題がそんなに多くなかったし、そこまで頭をひねるというわけでもなかったのは少し残念かもしれない。 とはいえ、単純なところで引っかかって時間を無駄にしてしまったり、そもそも準備不足で環境構築に時間を浪費する場面が多かったので、本戦に行く際には改善してゆきたい。 あと風邪を引いてしまったようなので、きちんと休んで回復したい。</p> <p>運営の皆さん、面白い問題をありがとうございました!</p> hikalium ISUCON8 本戦に出てまあまあだった話 hatenablog://entry/10257846132657034132 2018-10-20T22:58:06+09:00 2018-10-20T23:59:25+09:00 (この記事は本戦後の眠い頭を無理に回して書いています。どうか温かい目で読んであげてください…。) これまでのあらすじ 前回は、ISUCON8予選に出てガチャを引いたら運良く本戦に行けることになった!という話を書きました。 hikalium.hatenablog.jp というわけで今回は、本戦でどのようなことをしたのか、そしてその結果などをまとめてゆきたいと思います。 試合開始前 椅子CONではなく机CONだった 開場より少し早く会場に着いてしまったので、エレベーターホールで受付開始まで待っていたのですが、すでにかなりの人数が集まっていたのでびっくり。 入場開始するも、チームメイトのうさぎさん・… <p>(この記事は本戦後の眠い頭を無理に回して書いています。どうか温かい目で読んであげてください…。)</p> <h1>これまでのあらすじ</h1> <p>前回は、ISUCON8予選に出てガチャを引いたら運良く本戦に行けることになった!という話を書きました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhikalium.hatenablog.jp%2Fentry%2F2018%2F09%2F16%2F235250" title="ISUCON8の予選に出てみた - /var/log/hikalium" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://hikalium.hatenablog.jp/entry/2018/09/16/235250">hikalium.hatenablog.jp</a></cite></p> <p>というわけで今回は、本戦でどのようなことをしたのか、そしてその結果などをまとめてゆきたいと思います。</p> <h1>試合開始前</h1> <h2>椅子CONではなく机CONだった</h2> <p>開場より少し早く会場に着いてしまったので、エレベーターホールで受付開始まで待っていたのですが、すでにかなりの人数が集まっていたのでびっくり。</p> <p>入場開始するも、チームメイトのうさぎさん・megumishさんがまだ着いていなかったので、長蛇の列を横目に傍観していた。</p> <p>列も捌けてきたし、まだ二人が来ないので入場して会場のあるフロアへ。</p> <p>「机は各チームひとつくらいで」とのことだったので周囲を見回して見たところ、すでにけっこう埋まっていた。</p> <p>埋まっていないもっとも多くある机は、3人だとちょうどよいか少し肩身がせまいかも、という感じだった。</p> <p><blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ISUCON8 本戦にきています。<br>作業風景です(ちょっとせまい)。 <a href="https://t.co/2xrVzNjtR0">pic.twitter.com/2xrVzNjtR0</a></p>&mdash; hikalium (@hikalium) <a href="https://twitter.com/hikalium/status/1053449665880834053?ref_src=twsrc%5Etfw">2018年10月20日</a></blockquote><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p> <p>広めの机はすでに確保されていたし、空いている広い机は椅子に座って作業するには適していない低い机だったので、まあしょうがない。</p> <p>(もちろんたくさんのチームを招くために場所を確保するのはたいへんだったと思うのでありがたい限りだが、もう少し各チームの机が広かったらうれしいなあと思った。)</p> <h2>ストーリー説明</h2> <p>仮想椅子取引所ISUCOINというこれまた面白そうなテーマの背景ストーリーが説明された。あの人気<a class="keyword" href="http://d.hatena.ne.jp/keyword/SNS">SNS</a>、ISUBATAと連携!とか、過去問をやっていてわかるネタがあって、良く練られていると感じた。</p> <h1>試合の中身</h1> <p>私はインフラ要員として雇われた感じなので、アプリの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>そのものではなく、環境やDB, Webサーバの設定最適化を主に担当した。</p> <p>環境としては、2cpu, 1G mem のサー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC">バー</a>が4台与えられて、初期状態では各サーバでDB, <a class="keyword" href="http://d.hatena.ne.jp/keyword/Web%A5%B5%A1%BC%A5%D3%A5%B9">Webサービス</a>共に動作していた。</p> <p>目新しかった点は、サービスがDocker内で動いていたということである。Dockerよくわからん!となったので、とりあえず当初は、Dockerからアプリを引き剥がす作業に取り組むことになった。</p> <p>megumish氏はアプリ本体、私はDBとWebサーバをひっぺがす作業をした。</p> <p>今回はアプリが<a class="keyword" href="http://d.hatena.ne.jp/keyword/HTTPS">HTTPS</a>で動作していたため、当初何も考えずに<a class="keyword" href="http://d.hatena.ne.jp/keyword/certbot">certbot</a>で新しくグローバルの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>用にLetsEncryptで証明書を取ってきたりしたのだが、なんとベンチマーカは<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B0%A5%ED%A1%BC%A5%D0%A5%EBIP">グローバルIP</a>ではなくベンチマーカIPを対象にアクセスしており、そのIPにはグローバルの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>とは別の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>が割り当てられていたため、証明書エラーで<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>が落ちてしまった。これは、よくよくアプリの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C7%A5%A3%A5%EC%A5%AF%A5%C8">ディレクト</a>リを確認すると、Docker内のnginxが参照していた証明書が置いてあったため、それを証明書として指定してやればうまくいった。(ちょっと時間を無駄にしてしまった。)</p> <p>同時に、アプリの実装を、デフォルトの<a class="keyword" href="http://d.hatena.ne.jp/keyword/golang">golang</a>から<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>に変更する作業もした。ここまでの作業をしてdstatをつかってなんとなく状況を測定してみたところ、やはりCPUを食いつぶしていたので、次はDBを別サーバに分離することにした。</p> <p>このあたりだったか、うさぎさんがさくっとLIMIT 1の修正などを追加してくれて、これにより得点が700前後->2000超になった。</p> <p><a href="https://github.com/kmyk/isucon8-final/pull/6">https://github.com/kmyk/isucon8-final/pull/6</a></p> <p>アプリサーバとDBサーバを分けてから<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>を再度かけてみたところ、DBサーバのCPU使用率が高く、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CE%A7%C2%AE">律速</a>しているような雰囲気だった。</p> <p>ここでうさぎさんが、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%BD%A5%AF%C2%AD">ローソク足</a>の計算を毎回履歴を走査して計算することなく、アプリ起動時にキャッシュするようにすればよいのではないかと気づき実装してくれた。</p> <p><a href="https://github.com/kmyk/isucon8-final/pull/9">https://github.com/kmyk/isucon8-final/pull/9</a></p> <p>この修正により、<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>中のDBサーバのCPU利用率は、ベンチ開始時にどかんと上がり、すぐに低くなって低いまま走る、という感じになった。</p> <p>この、ベンチ開始時に急にCPU利用率が上がるという現象は、今後ロードバランシングする上で問題になりそうだったので、そもそも初期データに対する<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A1%BC%A5%BD%A5%AF%C2%AD">ローソク足</a>の計算は事前にやっておいてテーブルの初期データに挿入しておけばいいという話になり、その変更が入った。</p> <p><a href="https://github.com/kmyk/isucon8-final/pull/12">https://github.com/kmyk/isucon8-final/pull/12</a></p> <p>これにより、DBの利用率はかなり落ちて、またシェアボタンも確率的に出すようにしたところ( <a href="https://github.com/kmyk/isucon8-final/pull/10">https://github.com/kmyk/isucon8-final/pull/10</a> )、アプリが<a class="keyword" href="http://d.hatena.ne.jp/keyword/%CE%A7%C2%AE">律速</a>してきたような印象だったため、ロードバランシングをするようにしてみた。</p> <p><a href="https://github.com/kmyk/isucon8-final/pull/13">https://github.com/kmyk/isucon8-final/pull/13</a></p> <p>当初は2台でロードバランシングしていたが、それでも1台のサーバに対して<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>をかけて2台のサーバのCPU利用率が上がるのは、見ていて非常に楽しかった。</p> <p>と、ここに来て、連続でベンチを2回走らせると必ず事前チェックでfailするという問題が明らかになり、どうも初期に投入した、settingsのシングルトン化がバグっていたということがわかり、revertするなどした。</p> <p>megumish氏はこの裏で、ログ送信を即時ではなくキューイングして非同期に行う方法を模索していたのだが、それがなかなかうまくいかずこの辺りでチームの人々に疲れが相当見え始めた。</p> <p>結局最後は、全4台でアプリサーバをロードバランスしつつ、DBサーバはひとつという構成に落とし込んで、ガチャを回しつつ再起動テストに備える(ただし実際に再起動はしないで最後は祈る)ということをした。</p> <h1>結果</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181020/20181020235815.png" alt="f:id:hikalium:20181020235815p:plain" title="f:id:hikalium:20181020235815p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181020/20181020235848.png" alt="f:id:hikalium:20181020235848p:plain" title="f:id:hikalium:20181020235848p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>明らかに得点が伸び悩んだので、これはかなり厳しい結果だったのではないかと誰もが覚悟していたが、予想に反して全30チーム中12位の最終7475点(途中最高は7752点)、学生チームだけで見れば第4位と、そこまでひどくない成績を残せたようで、チームメン<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A1%BC">バー</a>一同少し心がやわらぎました。</p> <p>そして、なんと優勝は学生チームの「最大の敵は時差」で、35312点でした。すごい!おめでとうございます。</p> <p>社会人チームの「takedashi」は、最大で5万点超えを出していたようですが、再起動後に動作が不調で減点の結果、2位となったようです。残念(でもすごい)。</p> <h1>講評や反省</h1> <p>試合結果発表後、問題作成者による講評があったのですが、DBの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D1%A1%BC%A5%C6%A5%A3%A5%B7%A5%E7%A5%F3">パーティション</a>を解除しましたか?したほうが高速だったよ、という話を聞いて、それは気づかなかったなあ、まだまだ勉強が足りないな、と思いました。</p> <p>また、私が<a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>にそんなに慣れていないこともあって直接ロジックの改良に加われなかったこと、非同期処理や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C7%D3%C2%BE%C0%A9%B8%E6">排他制御</a>に関する知識の不足、そもそも練習不足なども多くあったなあと、反省する点が多く見つかりました。</p> <p>もちろん、これまで何度か練習をしたことで得た知見を活かせていた部分もあったので、もっとこれからもいろいろ知識を身につけてゆけばよいのですが。がんばってゆきたい!</p> <h1>感想</h1> <ul> <li>高レイヤ、まだまだ知らないことが多すぎる</li> <li>非同期・マルチスレッドの知識が薄かったので深めたい</li> <li>ISUCON楽しい!</li> </ul> <p>学生生活延長することになったし、来年も本戦に出られるよう精進します。次こそは優勝するぞ!</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/h/hikalium/20181020/20181020231226.jpg" alt="f:id:hikalium:20181020231226j:plain" title="f:id:hikalium:20181020231226j:plain" class="hatena-fotolife" itemprop="image"></span></p> hikalium ISUCON8の予選に出てみた hatenablog://entry/10257846132632459341 2018-09-16T23:52:50+09:00 2018-09-16T23:52:50+09:00 概要 CTFつながりでうさぎさんに声をかけていただき、megumishさんと3人で参加した。 チーム名は「受験生の仇」 13980点で学生枠8位で通過できた。 とにかくうさぎさんのギャンブル運の賜物である。 isucon.net なにをしたの 基本的にインフラまわりをしていた。 突然のh2oが登場してびっくりするなどした。h2o速いですね。 nginxに慣れていてログ取りとかもこれで用意していたので、最初はnginxに移行することを試みたが、微妙に遅い上にcsvファイルを上手く転送できずよくわからなくてあきらめた。 代わりにh2oのログフォーマットを書き換えて、alpで使えるようになおした。こ… <h1>概要</h1> <ul> <li>CTFつながりでうさぎさんに声をかけていただき、megumishさんと3人で参加した。</li> <li>チーム名は「受験生の仇」</li> <li>13980点で学生枠8位で通過できた。</li> </ul> <p><b>とにかくうさぎさんのギャンブル運の賜物である。</b></p> <p><iframe src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fisucon.net%2Farchives%2F52459414.html" title="ISUCON8 2日目の結果と本選出場者決定のお知らせ : ISUCON公式Blog" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="http://isucon.net/archives/52459414.html">isucon.net</a></cite></p> <h1>なにをしたの</h1> <p>基本的にインフラまわりをしていた。</p> <p>突然のh2oが登場してびっくりするなどした。h2o速いですね。</p> <p>nginxに慣れていてログ取りとかもこれで用意していたので、最初はnginxに移行することを試みたが、微妙に遅い上に<a class="keyword" href="http://d.hatena.ne.jp/keyword/csv">csv</a>ファイルを上手く転送できずよくわからなくてあきらめた。</p> <p>代わりにh2oのログフォーマットを書き換えて、alpで使えるようになおした。これでやっと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%EA%CE%CC">定量</a>的にパフォーマンスをみることができるようになった。</p> <p>あと<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>のプロファイラも事前の練習で出来上がっていたものを使えるようにセットアップしたりしていた。あまり使わなかったけれど。</p> <p>最初は一台のサーバでWebサーバもDBサーバも動かしていたけれど、htopとかdstatでみていた感じ、メモリが飽和していて苦しそうだったので分けてあげることにした。</p> <p>分けたことで、DBサーバにメモリをたくさん食べさせてあげることができてDBもうれしそうな悲鳴をあげていた。</p> <p>初めてMySQLTunerをつかってみた。だいたいはおすすめ通りでいい感じだったが、一部おすすめ通りだとメモリが少なすぎるのかDBが死んだので適宜調整した。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Fmajor%2FMySQLTuner-perl" title="major/MySQLTuner-perl" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/major/MySQLTuner-perl">github.com</a></cite></p> <p>あとは、アプリ側の小さな修正をしたり、二人のプルリクをレビュー&amp;マージしたり、ロードバランシングできないかなーと試すなどしていた(firewalldさんの存在を忘れかけていて頭をひねっていた)。</p> <p>最後はみんながベンチを投げた時のDBサーバの負荷を見て「あ、落ちたね」「終わった」とか呟くボットになっていました。</p> <h1>結果</h1> <p>最後にうさぎさんがスロットを回し続けたおかげでなんとか13980点に到達した。最後の賭けが外れていたら本戦には行けていなかった。</p> <p>一応再起動のことを考えてsystemctlまわりの設定は見直していたものの、追試で落ちないことを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A7%A4%EA">祈り</a>続けていた。祈るだけじゃなくて検証したいものですね。</p> <h1>感想</h1> <p>運良く本戦に行けることになったので、次は実力で勝負したいところ。</p> <p>バイナリ問が出るといいなー。(これはCTFではない。)</p> <p>あと、学生チームが強い。(昨年同じチームで出て予選敗退した人が今回別のチームで出ていたのだが、我々よりずっと高得点を叩き出していて、学生なのに普通の枠で通過しており、さすがだと思った。)</p> <p>みなさまどうかお手柔らかにお願いいたします…。</p> <h1>チームメンバーの参加記</h1> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fkimiyuki.net%2Fblog%2F2018%2F09%2F16%2Fisucon8-quals%2F" title="ISUCON8 予選 参加記" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://kimiyuki.net/blog/2018/09/16/isucon8-quals/">kimiyuki.net</a></cite></p> hikalium 思い立っておうちネットワークにdnsmasqを建てた話 hatenablog://entry/10257846132598440160 2018-07-06T01:25:15+09:00 2018-07-06T01:55:41+09:00 概要 ホストとipの結びつきや、固定ipの利用状況の管理が ~/.ssh/config 頼りだったので改善したかった とりあえず善は急げでdnsmasqを建てた Ubuntu 18.04ではsystemd-resolvedが53をLISTENしていて手間取った 環境 $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04 LTS" 動機 ふとRaspberry pi で遊びたくなったんです。そんな日もありますよ… <h2>概要</h2> <ul> <li>ホストとipの結びつきや、固定ipの利用状況の管理が <code>~/.ssh/config</code> 頼りだったので改善したかった</li> <li>とりあえず善は急げでdnsmasqを建てた</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a> 18.04ではsystemd-resolvedが53をLISTENしていて手間取った</li> </ul> <h2>環境</h2> <pre class="code" data-lang="" data-unlink>$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION=&#34;Ubuntu 18.04 LTS&#34;</pre> <h2>動機</h2> <p>ふと<a class="keyword" href="http://d.hatena.ne.jp/keyword/Raspberry%20pi">Raspberry pi</a> で遊びたくなったんです。そんな日もありますよね。</p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>どれにしていたかなーと思いつつ、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Wireshark">Wireshark</a>で<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>のパケットを見張って特定して無理やり<a class="keyword" href="http://d.hatena.ne.jp/keyword/SSH">SSH</a>するなどして、とりあえずアクセスはできました。</p> <p>あとのことも考えて、そうだ<a class="keyword" href="http://d.hatena.ne.jp/keyword/IP%A5%A2%A5%C9%A5%EC%A5%B9">IPアドレス</a>を固定しようと思った時に、気づいたわけです。</p> <p>「どのアドレスが空いてるんだっけ?」</p> <p>まあ、手元の端末の <code>~/.ssh/config</code>を参照すればだいたい書いてあったので、そこから適当に選んでIPを振ったのはよかったのですが、本当はかっこよく<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>でシュッと引けたら気分がいいですよね?そうしましょう!</p> <h2>やったこと</h2> <p>dnsmasq を使うことにしました。bindっていう規模でもなかったので。aptですぐ入るのが便利。</p> <pre class="code" data-lang="" data-unlink>sudo apt install dnsmasq</pre> <p>ところがインストール直後に不穏なメッセージが。</p> <pre class="code" data-lang="" data-unlink>dnsmasq: failed to create listening socket for port 53: アドレスは既に使用中です</pre> <p>え?いつの間に<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>サーバーが!?誰だ建てたのは!外部からの侵入か?と冷や汗をかいたが犯人は <code>systemd-resolved</code> でした。 (<a class="keyword" href="http://d.hatena.ne.jp/keyword/127.0.0.1">127.0.0.1</a>:53 だけだったので、外からはアクセスできませんでしたが。)</p> <p>以下の記事も同じような状況に遭遇して同じような反応をしていました。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2Fshooskay%2Fitems%2Fa4f7b61bfe4c3a0d578e" title="127.0.0.53:53 って 誰が 使ってるの? - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://qiita.com/shooskay/items/a4f7b61bfe4c3a0d578e">qiita.com</a></cite></p> <p>結局 <code>systemd-resolved</code>をdisableすることにしました。以下の投稿の通りにすればOKだった。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Faskubuntu.com%2Fa%2F907249" title="How to disable systemd-resolved in Ubuntu?" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://askubuntu.com/a/907249">askubuntu.com</a></cite></p> <p>設定は基本的に以下で述べられている例を参考にすれば良いと思います。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fint128.hatenablog.com%2Fentry%2F20120226%2F1330247800" title="dnsmasqで始めるプライベートDNSサーバ - GeekFactory" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://int128.hatenablog.com/entry/20120226/1330247800">int128.hatenablog.com</a></cite></p> <p>また、 <code>/etc/hosts</code>をdnsmasq用に使うと、dnsmasq自体を走らせているサーバーのホストについて<a class="keyword" href="http://d.hatena.ne.jp/keyword/127.0.0.1">127.0.0.1</a>を返すことになります。これでは悲しいので、<code>/etc/dnsmasq.conf</code>に</p> <pre class="code" data-lang="" data-unlink>no-hosts addn-hosts=/etc/hosts-dnsmasq</pre> <p>と記述し、<code>/etc/hosts</code>は読み込まず、代わりに<code>/etc/hosts-dnsmasq</code>を利用するように設定しました。</p> <h2>おまけ:<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>サーバに<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>サーバと<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%C9%A5%E1%A5%A4%A5%F3">ドメイン</a>名を設定する(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Cisco">Cisco</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%BF%A1%BC">ルーター</a>の場合)</h2> <p>ここまで設定したら、端末側の<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>サーバ設定も<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>経由で自動的に設定してあげたいですよね。私のネットワークでは、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Cisco">Cisco</a>の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EB%A1%BC%A5%BF%A1%BC">ルーター</a>が<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>サーバーになっているので、その設定も変更しておくことにします。</p> <p>ルータのバージョンは以下の通りです。</p> <pre class="code" data-lang="" data-unlink>Cisco IOS Software, C800M Software (C800M-UNIVERSALK9-M), Version 15.7(3)M2, RELEASE SOFTWARE (fc2)</pre> <h3>手順</h3> <ol> <li><code>show ip dhcp pool</code> で<a class="keyword" href="http://d.hatena.ne.jp/keyword/dhcp">dhcp</a> poolの名前を確認しておきます。</li> <li><code>configure terminal</code> に入って、<code>ip dhcp pool &lt;dhcp pool名&gt;</code>を実行して該当poolの設定に入ります。</li> <li><code>dns-server &lt;DNSサーバのアドレス&gt;</code> <code>domain-name &lt;ネットワークのドメイン名&gt;</code> としたのち、<code>exit</code>して<code>write mem</code>します。</li> </ol> <p>これで、各端末の<a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>リースを更新すれば、ホスト名だけで<a class="keyword" href="http://d.hatena.ne.jp/keyword/ssh">ssh</a>したりできるようになっているはずです。やったね!</p> <h2>まとめ</h2> <ul> <li>dnsmasqをインストールして、かんたんな内部向け<a class="keyword" href="http://d.hatena.ne.jp/keyword/DNS">DNS</a>サーバを建てた。</li> <li>新しい<a class="keyword" href="http://d.hatena.ne.jp/keyword/Ubuntu">Ubuntu</a>では、<code>systemd-resolved</code>がすでにPort 53をLISTENしているので、これをdisableにした。</li> <li><code>/etc/dnsmasq.conf</code>はこんな感じ。</li> </ul> <pre class="code" data-lang="" data-unlink>domain-needed bogus-priv local=/local.hikalium.com/ no-hosts addn-hosts=/etc/hosts-dnsmasq expand-hosts domain=local.hikalium.com</pre> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/DHCP">DHCP</a>サーバの設定もいじっておきましょう!</li> </ul> hikalium