lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2015-05-19 7:50 GMT+02:00 "书呆彭, Peng Yi" <nerditation@outlook.com>:
> 在 2015/5/19 0:32, Philipp Janda 写道:
>>
>> Hi!
>>
>> Is it supported to enumerate/query the local variables of a function from
>> within a return hook?
>>
>
> local variables are scoped; as I understand, the when the return hook get
> called, it still _within_ the
> returning function. the manual says
> [http://www.lua.org/manual/5.3/manual.html#lua_sethook]:
>
>   The return hook:  is called when the interpreter returns from a function.
>                     The hook is called *just before* Lua leaves the
> function.
>                     There is no standard way to access the values to be
> returned by the function.
>
>
>> I have some difficulties on all Lua versions since 5.1:
>>
>> Lua 5.1:
>>
>>     func    a    10
>>     func    b    table: 0x18338e0
>>     func    c    function: 0x182e890
>>     func    d    true
>>     func    e    string
>>
>> (apparently all locals are already gone).
>>
>> Lua 5.2:
>>
>>     func    a    10
>>     func    b    table: 0x1b3ed10
>>     func    c    function: 0x1b3f4c0
>>     func    d    true
>>     func    e    string
>>
>>     HOOK    a    table: 0x1b3fbc0
>>     HOOK    b    function: 0x1b3c850
>>     HOOK    c    3
>>     HOOK    d    c
>>     HOOK    e    c
>>
>> (local variable names are still there, values are wrong)
>>
>> Lua 5.3:
>>
>>     func    a    10
>>     func    b    table: 0x8fbc80
>>     func    c    function: 0x8fbcc0
>>     func    d    true
>>     func    e    string
>>
>>     HOOK    a    table: 0x8f77b0
>>     HOOK    b    function: 0x8f7590
>>     HOOK    c    3
>>     HOOK    d    c
>>     HOOK    e    c
>>
>> (same as 5.2)
>>
>> LuaJIT seems to manage:
>>
>>     func    a    10
>>     func    b    table: 0x40622d08
>>     func    c    function: 0x4061f780
>>     func    d    true
>>     func    e    string
>>
>>     HOOK    a    10
>>     HOOK    b    table: 0x40622d08
>>     HOOK    c    function: 0x4061f780
>>     HOOK    d    true
>>     HOOK    e    string
>>
>> Test script attached.
>>
>
> I checked the attached script and examined the source code of Lua.
> interestingly, if you return something (even `nil') instead of nothing from
> that function,
> you'll get the expected result (I have Lua 5.2 installed, but I believe it
> applies to 5.3):
>
> --------------------------
>   func    a       10
>   func    b       table: 000000000052BB20
>   func    c       function: 000000000052CDE0
>   func    d       true
>   func    e       string
>
>   HOOK    a       10
>   HOOK    b       table: 000000000052BB20
>   HOOK    c       function: 000000000052CDE0
>   HOOK    d       true
>   HOOK    e       string
> ---------------------------
>
> for me, it feels like a bug (or call it a glitch) of Lua in this special
> situation.
> I'll explain it in detail.
>
> Lua calls the debug hook in function `luaD_poscall' (ldo.c), which is called
> by the VM
> when executing the OP_RETURN instruction (lvm.c). but the OP_RETURN
> instruction will first
> adjust the stack, according to the returning values.
> this is all good, except when the function returns NOTHING, in which case
> the RA register
> of OP_RETURN is 0, so the VM simply empty the the (still semantically
> active) stack frame.
> thus you actually get values probably located in the stack frame of the hook
> itself
> when you call debug.getlocal.
>
>
> when the function returns NOTHING (either an explicit `return' statement or
> implicitly),
> Lua generate this opcode:
>
>   RETURN 0 1
>
> when the function returns some value (e.g. nil), Lua generate this opcode:
>
>   LOADNIL 8 0
>   RETURN 8 2
>
> in the latter case, the VM still adjust the stack before calling the return
> hook, but since
> the returnning values are loaded at the top of the stack, the active stack
> frame holding the
> local variables is not destroyed, so your hook can now get the expected
> results.

Something else that may also be relevant: Lua always generates an empty
return even when you have other returns, but it is not reached if you
have enough real returns. Maybe it is only when you execute that empty
return that the problem arises. I.e. an explicit return nothing higher up
may still be OK. I don't have the time to try it out right now.