Lua

7月になってスーパーの袋が有料化された。これはたまらんと女房がトートバッグを引っ張り出した。No Ruby, No Life. って奴。rubyの伝道師を務めるんだな。オイラーはLuaの伝道師(今の所は)を務めます。

wireshark

前回の調べでは、wiresharkにもluaが使われいるそうなので、本当か最新の3.2.5で確認してみた。確かに使われていたよ。でも、その位置付けを明確に読み取れず。

悔しいので、ソースが有るんでbuildしてみた。mkdir build; cd build; cmake .. なんだけど、GUIを作るQtの環境を用意しないとならない。潔く諦める。乗りかけた船なんで、GUI無しでやってみる。

debian:build$ cmake  -DBUILD_wireshark=OFF ..
debian:build$ make
 :
[100%] Built target fuzzshark

real    27m24.164s
user    24m58.925s
sys     1m42.720s

run/ の下に出来ている tshark あたりが核になるのかな。tshark.htmlを軽く眺めてみると、tcpdumpの超拡張版のように取れるんだけど。

GUIなんて、皮だからどうでも良い。『UNIXという考え方』新人エンジニアにオススメする技術書 懐かしい本が出て来た。昔読んだ時、そうだよね。マウスでぐりぐりって人が張り付いて作業しなきゃならない方式。オイラーは疲れちゃう。

そこで、スーパーコンピュータ「不老」 ですよ。不老はフロー。フローと言えば、データが流れてくるパイプですよ。ちょっとした事をやりたい場合、スクリプトを書く前に、それってパイプにデータを流して処理出来ないか、真っ先に考えます。それもこれも、unixの偉大な発明、パイプが有ったればこそです。

puTTY 0.74

OpenBSDにpuTTYから接続出来なくなっていた。もう10年も使っている年代物の0.60版だったからしょうがないと諦めていたんだ。

最近、0.74版が出たというので取り寄せてみた。PuTTY: a free SSH and Telnet client そしたら、無事に使えた。zip版を適当な所に置いただけなんだけど、ちゃんと前に使ってた設定が生きていて、何の苦もなく利用出来た。

それはいいんだけど、設定はどこに残っているのかな。前の版もWindows7時代のやつを、そのままdir事Windows10に持ってきただけなんで、古い版の設定なんてM$の管理化には無いはずなんだけどな。

兎も角、これで3wayで接続出来るようになった。PuTTYでの接続、Windows terminalでの接続、Tera Termによるシリアル接続。各種用意してあれば、どれかで接続出来る、安泰である。

世は、WSL2でWindowsにべったりなLinuxってのが流行る兆候が有るけど、なるべくWindowsとは距離を置いておいた方が安心と思うぞ。それにWSL2はリナしか動かなくて、面白く無いしょ。

上で挙げた、puTTYの設定はどうなってる疑問の答えがFAQに出てた。Windowsが用意したDBに保存してますと。だからpuTTYを削除する時は、先に下記の操作をしておけとな。

putty -cleanup

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY こういう場所に保存されるそうな。だから、MobaXtermが軽々と設定を利用出来たんだな。納得です。

lua

追試

上のリンクにもあるように、GCの方式が変わったとな。debian(32it)で試した時は、にわかに信じられないような差が付いていたので、64Bitの方でも試してみる。 debian(64Bit)

sakae@pen:/tmp/lua-5.3.5/src$ time ./lua tak.lua
real    0m28.311s
user    0m28.306s
sys     0m0.004s
sakae@pen:/tmp/lua-5.4.0/src$ time ./lua tak.lua
real    0m22.776s
user    0m22.769s
sys     0m0.000s

おまけで、OpenBSD(64Bit)

ob$ ./lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
ob$ time ./lua tak.lua
    0m35.18s real     0m35.18s user     0m00.02s system
ob$ ./lua -v
Lua 5.4.0  Copyright (C) 1994-2020 Lua.org, PUC-Rio
ob$ time ./lua tak.lua
    0m32.65s real     0m32.66s user     0m00.00s system

これぐらいの差が妥当な所だと思われる。

lua温故知新

余り新しい物ばかりを追う前に、古いのも見てみろ。ソフトは積み重ねだからね。 そんな訳で、適当に古いと思われる、5.1.5を取ってきた(この版に他意は無い)。

min

今の物と違っておまけが付いていた。まずはetcの中のやつ。

debian:etc$ make min
gcc -O2 -Wall -I../src  min.c -L../src -llua -lm
echo 'print"Hello there!"' | ./a.out
Hello there!

簡単なprint文を呼び出すだけなやつ。勿論、事前にluaをコンパイルしておく事。 で、下記のようにしてgdbで取り調べをしてみる。

debian:etc$ cat Z
print "Hello there!"
debian:etc$ gdb -q a.out
Reading symbols from a.out...
(gdb) b print
Breakpoint 1 at 0x14d0: file min.c, line 14.
(gdb) r <Z
Starting program: /tmp/lua-5.1.5/etc/a.out <Z

Breakpoint 1, print (L=0x41f160) at min.c:14
14       int n=lua_gettop(L);
(gdb) bt
#0  print (L=0x41f160) at min.c:14
#1  0x00404a92 in luaD_precall (L=<optimized out>, func=0x41f3a8, nresults=0)
    at ldo.c:320
#2  0x0040dc8d in luaV_execute (L=<optimized out>, nexeccalls=1) at lvm.c:591
#3  0x00404fbb in luaD_call (L=0x41f160, func=0x41f39c, nResults=-1)
    at ldo.c:378
#4  0x00401625 in f_call (L=0x41f160, ud=0xbffff3f8) at lapi.c:800
#5  0x00404395 in luaD_rawrunprotected (L=0x41f160, f=0x401610 <f_call>,
    ud=0xbffff3f8) at ldo.c:116
#6  0x00405179 in luaD_pcall (L=0x41f160, func=0x401610 <f_call>,
    u=0xbffff3f8, old_top=12, ef=0) at ldo.c:464
#7  0x00402a0b in lua_pcall (L=0x41f160, nargs=0, nresults=-1, errfunc=0)
    at lapi.c:821
#8  0x00401339 in main () at min.c:36

trace-call

test/の中にも、面白いものがあった。とある関数の根もバイナリーサーチに見つけるというluaの例。

debian:test$ lua bisect.lua
0 c=1.5 a=1 b=2
1 c=1.25 a=1 b=1.5
:
20 c=1.3247179985046 a=1.3247175216675 b=1.3247184753418
after 20 steps, root is 1.3247179985046387 with error 9.5e-07, f=1.8e-07

本命はこれじゃなくて、どんな風に関数が呼び出されているか、トレースしちゃいましょって言う、luaで書かれたライブラリィー。

debian:test$ head trace-calls.lua
-- trace calls
-- example: lua -ltrace-calls bisect.lua

トレーサーの冒頭に、使い方が出てた。-lでライブラリー呼び出しになる。サフィックスは付けないという約束。これだけ分かれば良い。

debian:test$ lua -ltrace-calls bisect.lua
0 >>> ./trace-calls.lua:31 return sethook [C]
0 >>> end ./trace-calls.lua
0 >>> return (C) [C]
0 >>> begin bisect.lua
1 >>>  bisect.lua:27 call solve <15:bisect.lua>
2 >>>   bisect.lua:17 call f <22:bisect.lua>
3 >>>    bisect.lua:17 return f <22:bisect.lua>
2 >>>   bisect.lua:17 call f <22:bisect.lua>
3 >>>    bisect.lua:17 return f <22:bisect.lua>
2 >>>   bisect.lua:17 call bisect <5:bisect.lua>
3 >>>    bisect.lua:7 call write [C]
0 c=1.5 a=1 b=2
4 >>>     bisect.lua:7 return write [C]
3 >>>    bisect.lua:8 call abs [C]
4 >>>     bisect.lua:8 return abs [C]
:
after 20 steps, root is 1.3247179985046387 with error 9.5e-07, f=1.8e-07
1 >>>  bisect.lua:18 return write [C]
0 >>> bisect.lua:27 return solve <15:bisect.lua>
0 >>> end bisect.lua
0 >>> return (C) [C]

debugライブラリーをhookして実現してる。楽しそうである。

luadec

何か、こう道具を集めるのが趣味と化している。ならば、逆アセンブラーなんてのが欲しいと思っちゃうな。探してみたら直ぐに見つかった。

LuaDec is a Lua decompiler for lua 5.1 , and experimental for lua 5.2 and 5.3.

色々な所で隠れluaしてるんで、こういうのも有志が作ってくれているんだな。 早速試してみるか。

vbox$ cat hoge.lua
function hoge(a,b)
   local t = a^2
   return t + b
end
print( hoge(2,3) )
vbox$ luadec -dis hoge.lua
; Disassembled using luadec 2.2 rev: 895d923 for Lua 5.1 from https://github.com/viruscamp/luadec
; Command line: -dis hoge.lua

; Function:        0
; Defined at line: 0
; #Upvalues:       0
; #Parameters:     0
; Is_vararg:       2
; Max Stack Size:  4
    0 [-]: CLOSURE   R0 0         ; R0 := closure(Function #0_0)
    1 [-]: SETGLOBAL R0 K0        ; hoge := R0
    2 [-]: GETGLOBAL R0 K1        ; R0 := print
    3 [-]: GETGLOBAL R1 K0        ; R1 := hoge
    4 [-]: LOADK     R2 K2        ; R2 := 2
    5 [-]: LOADK     R3 K3        ; R3 := 3
    6 [-]: CALL      R1 3 0       ; R1 to top := R1(R2 to R3)
    7 [-]: CALL      R0 0 1       ;  := R0(R1 to top)
    8 [-]: RETURN    R0 1         ; return
; Function:        0_0
; Defined at line: 2
; #Upvalues:       0
; #Parameters:     2
; Is_vararg:       0
; Max Stack Size:  4
    0 [-]: POW       R2 R0 K0     ; R2 := R0 ^ 2
    1 [-]: ADD       R3 R2 R1     ; R3 := R2 + R1
    2 [-]: RETURN    R3 2         ; return R3
    3 [-]: RETURN    R0 1         ; return

lhades

もう一つ日本人が書かれた、逆アセンブラを見つけた。lua 5.3.5 専用なのかな。

Lua5.3の逆アセンブラを書いたこと

インストールには業界標準のパッケージマネージャ luarocks を使っている。rubyで言うgemなんだな。こういう周辺ツールが提供されてるって事は、成熟してる証拠だ。

何はともあれ、走らせてみる。例は上でやったやつ。

sakae@pen:/tmp$ luac hoge.lua
sakae@pen:/tmp$ lhades luac.out
.codes: 9
  [1] CLOSURE         0               0    ; R(0) := closure(KPROTO[0])
  [2] SETTABUP        0     256       0    ; UpValue[0][RK(256)] := RK(0)
  [3] GETTABUP        0       0     257    ; R(0) := UpValue[0][RK(257)]
  [4] GETTABUP        1       0     256    ; R(1) := UpValue[0][RK(256)]
  [5] LOADK           2               2    ; R(2) := Kst(2)
  [6] LOADK           3               3    ; R(3) := Kst(3)
  [7] CALL            1       3       0    ; R(1), ... ,R(1+0-2) := R(1)(R(1+1), ... ,R(1+3-1))
  [8] CALL            0       0       1    ; R(0), ... ,R(0+1-2) := R(0)(R(0+1), ... ,R(0+0-1))
  [9] RETURN          0               1    ; return R(0), ... ,R(0+1-2)
.consts: 4
  [0] "hoge"
  [1] "print"
  [2] 2
  [3] 3
.upvalues: 1
  [0] inStack: true, index: 0    ; _ENV
.locals: 0
.protos: 1
  [0] source name "@hoge.lua": 1 - 4: 2 params, 4 stacks
    .codes: 4
      [1] POW             2       0     256    ; R(2) := RK(0) ^ RK(256)
      [2] ADD             3       2       1    ; R(3) := RK(2) + RK(1)
      [3] RETURN          3               2    ; return R(3), ... ,R(3+2-2)
      [4] RETURN          0               1    ; return R(0), ... ,R(0+1-2)
    .consts: 1
      [0] 2
    .upvalues: 0
    .locals: 3
      [0] "a" (0 - 4)
      [1] "b" (0 - 4)
      [2] "t" (1 - 4)
    .protos: 0

素晴らしい!!

LuaRocks

LuaRocks が、本拠地。提供されてるモジュールの人気なやつが列挙されてたりする。何となく使われている業界が想像出来たりして。

どうもメインはLinuxとWindowsっぽい。まあ、しょうがないか。

こういうパッケージマネージャが出てくると、オイラーは何となく、引いちゃうんだよな。

上のlhadesを素でコンパイルしようとすると、

sakae@pen:/tmp/lhades$ make
g++ -std=c++1y -I -o src/proto.o -c src/proto.cpp
g++: error: src/proto.o: No such file or directory
make: *** [Makefile:16: src/proto.o] Error 1

こういう、わけわかめなエラーになる。Makefileを見ても素直な奴に思える。いや、眼をこらして見ると、

$(CXX) $(CFLAGS) -I$(LUA_INCDIR) -o $@ $^

この LUA_INCDIR は何? こういう変数を使われてしまうと、困っちゃうぞ。

sakae@pen:/tmp/lhades$ cat lhades-0.1-1.rockspec
 :
build = {
        type = "make",
        build_variables = {
                LUA_INCDIR = "$(LUA_INCDIR)",
        },

luarocksが、無駄な介入をしてるっぽい。

sakae@pen:/tmp/lhades$ LUA_INCDIR=/usr/local/include make
g++ -std=c++1y -I/usr/local/include -o src/proto.o -c src/proto.cpp
 :
g++ -std=c++1y -I/usr/local/include -o lhades src/proto.o src/reader.o src/upvalue.o src/writer.o src/code.o src/header.o src/constant.o src/main.o src/debug_info.o

g++の非常に不親切(それが伝統よ)なエラー表示によって、無駄な労力を要求されるってどうよ。それを解消する為に luarocks が有るとすれば、情けない限りだ。これが、LinuxとWindows屋の労力削減に役だっているんだな。ブラックボックス増長に断固反対します。

rubyと疎遠になったのも、gemなんて言う余計な奴が幅を利かせるタイミングだったな。

socket

luarocksを入れた時、お試しでsocketパッケージも入れた(ってか、指示通りにしたら入ってしまったのが真相)。折角なんで探ってみる。

sakae@pen:/usr/local/lib/luarocks/rocks-5.3/luasocket/3.0rc1-2$ ls
doc  etc  luasocket-3.0rc1-2.rockspec  rock_manifest  samples  test

gitで提供されてる部分を保存してくれているんだな。ちょいと試してみるか。

sakae@pen:samples$ lua echosrvr.lua 127.0.0.1 2929
Binding to host '127.0.0.1' and port 2929...
Waiting packets on 127.0.0.1:2929...
timeout
timeout
Echoing 'hello' to 127.0.0.1:49192

まずサーバーを起動。パケットが届かないと、しびれをきらして、timeoutなんて言って来るのね。はいはい、クライアントを立ち上げますよ。

sakae@pen:samples$ lua echoclnt.lua localhost 2929
Using remote host '127.0.0.1' and port 2929...
hello
hello

どんなコードになってるか、覗き見。

local socket = require("socket")
 :
assert(udp:settimeout(5))
ip, port = udp:getsockname()
assert(ip, port)
print("Waiting packets on " .. ip .. ":" .. port .. "...")
while 1 do
        dgram, ip, port = udp:receivefrom()
        if dgram then
                print("Echoing '" .. dgram .. "' to " .. ip .. ":" .. port)
                udp:sendto(dgram, ip, port)
        else
        print(ip)
    end
end

サーバーの主要部分は、こんな感じ。5秒待ってパケが来ないと文句を言うようにしてるのね。luaで文字列の連結は、".." だ。そしてperlっぽく、数値はその場で佳きに計らえで文字列に変換される。(逆に文字列を数字に自動変換する場合もある)

socketのパッケージは、coreの部分がC語で書いてあり、それがコンパイルされてcore.soとかになり、/usr/local/lib/lua/5.3/socket に置かれている。 スピードが必要無い、緩い部分は、/usr/local/share/lua/5.3 に鎮座してる。

こういう土地勘が大事だぞ。

etc

LUPE - Lua Debugger

C と lua の連携方法メモ

wiresharkのプラグイン開発まとめ これを見てluaの位置付けが良く分かったよ。pythonを採用しなかった作者は偉いな。


This year's Index

Home