#
debug
This is an expansion to the existing Lua debug library.
This allows you to create many ways of accessing data that would be otherwise impossible.
As well as providing security features for safety of instrusions to lua-based APIs not from the Interstellar Engine.
Expansion Library
This is an expansion to builtins provided by Lua itself, see more about them on the official Lua/LuaJIT wikis.
#
Functions
debug.getfenv(obj: function | number): table?
- Returns the environment of object obj.
- This differs a bit from the base function getfenv, which takes a function or a level number, and converts the level number into a function.
debug.gethook(thread: thread | function | number): function, number, number
- Returns the current hook settings as three values: Hook Function, Mask, Count
debug.getinfo(thread: thread | function | number, field?: string, what?: function): table
- Returns a table with information about a function or stack level
f - returns "func" field
l - returns "currentline" field
L - returns a table whose indices are the numbers of the lines that are valid on the function. (A valid line is a line with some associated code, that is, a line where you can put a break point. Non-valid lines include empty lines and comments.)
n - returns "name" and "namewhat" fields
S - returns "source", "short_src", "linedefined" and "what" fields
u - returns "nups" field
debug.getlocal(level: number, local: number): string, any
- Returns the name and value of the local variable with the index 'local' of the function at 'level' on the stack.
debug.getmetatable(obj: proto | function | table | userdata): table?
- Returns the metatable of the given object or nil if it does not have a metatable.
debug.getregistry(): table
- Returns the registry table, which is a special table used by C functions to store information it wants to keep isolated from Lua functions.
- This can act as permanent storage for variables to be retreived later on.
debug.getupvalue(level: number | function, upvalue: number): string, any
- Similar to debug.getlocal, returns the names and values of the upvalues for the nominated function.
debug.setfenv(obj: function | number, tbl: table): any
- Sets the environment of the given object to the given table, returns the object.
debug.setlocal(obj: function | number, local: number, value: any)
- Sets the value of the local variable with the index 'local' of the function at 'level' on the stack.
debug.sethook(thread: thread | function | number, f?: function, mask?: number, count?: number)
- Sets the function f as a hook to be called when the "mask" condition is satisfied.
- If count is non-zero, it is called after every "count" instructions.
- The thread argument is optional and defaults to the current thread.
- If called without arguments, turns off the hook.
- The function f is called with its first parameter being a string, which can be one of:
call, return, tail return, line, count
c - called every time Lua calls a function
r - called every time Lua returns from a function
l - called every time Lua enters a new line of code
debug.setmetatable(obj: proto | function | table | userdata, tbl: table): any
- Sets the metatable for the given object to the given table (which can be nil).
- Bypasses the check for the "__metatable" entry.
- Returns the object.
debug.setupvalue(level: number | function, upvalue: number, value: number)
- Similar to debug.setlocal, sets the values of the upvalue for the nominated function.
debug.traceback(thread?: number | function | string, message?: string, level?: number)
- Returns a string with a traceback of the stack call.
- An optional message string is prepended to the beginning of the traceback message.
#
Extension
debug.registry(): table
- Gets the true debug registry table.
- This table is used to keep permanent objects, preventing GC from removing them.
debug.global(): table
- Gets the true global table.
debug.env(): table
- Gets the current stack's environment.
debug.detour(target: function, detour: function): function
- Creates a memory-based hook towards a target lua function or C function.
debug.isdetour(target: function): boolean
- If a function has a memory-mapping to another function.
debug.original(target: function): function
- If a function has a memory-mapping, this will return the original.
debug.restore(target: function)
- Restores the memory-mapped function.
local original
original = debug.detour(print, function(...)
MsgC( Color( 255, 0, 0 ), "[Detour working!]" )
return original(...)
end)
print("This is a test!") -- Outputs: [Detour working!]This is a test!
if debug.isdetour(print) then
print("The `print` function has been detoured.")
else
print("The `print` function is not detoured.")
end
local original_print = debug.original(print)
original_print("This bypasses the detour!")
debug.restore(print) -- Restores the original `print` function.
print("Detour has been restored!") -- Outputs normally without detour.
debug.clone(value: function | proto | userdata): function | proto | userdata
- Copys a value in memory, creating a completely new value but with the same characteristics.
local original_func = function(a, b) return a + b end
local cloned_func = debug.clone(original_func)
print(original_func(5, 3)) -- Output: 8
print(cloned_func(5, 3)) -- Output: 8 (cloned function has the same behavior)
debug.replace(target: function | proto | userdata, value: function | proto | userdata)
- Replaces a value by reference in memory, effectively replacing all occurences of it.
local original = function() print("original call!") end
local replaced = function() print("replaced call!") end
original()
debug.replace(original, replaced) -- replace, now its gonna print "replaced call!" instead of "original call!"
original()
debug.newcclosure(func: function): function
- Creates a new cfunction closure which is untraceable.
debug.getgc(iterator?: boolean): (table | function | proto | userdata)[] | function
- Gets the garbage collector table.
- This has iterator functionality in foreach-loops.
- Do note this contains every value in existance.
debug.topointer(data: any, str: boolean): string | number
- Converts a datatype into it's absolute pointer location.
- Output looks like this:
"0xd8ad9caa"
or3635244450
debug.frompointer(ptr: number): function | table | proto | userdata
- Scans memory to find the pointer association.
debug.toproto(f: function): proto
- Converts an function to a prototype object
debug.fromproto(p: proto): function
- Converts an prototype into a function handle
- Do note this creates a completely new function
debug.getconstant(f: function, index: number): any
- Gets a function's constant by their index
debug.getconstants(f: function): {[index: string]: any}
- Gets all constants from a function
debug.setconstant(f: function, index: number, value: any): boolean
- Sets a constant in a function at an index
- Returns a
boolean
on if it was able to do so
debug.iscfunction(f: function): boolean
- Checks if the provided function is made by "C"
debug.islfunction(f: function): boolean
- Checks if the provided function is made by "Lua"
debug.setbuiltin(func: cfunction, ffid: number)
- Changes a cfunction to be a Fast Function with an ID.
- This will make them appear as
"builtin: xx"
- Use newcclosure if you plan to make a detour with this.
debug.getbuiltin(func: cfunction): number
- Gets the ffid number of a cfunction.
debug.getupvalues(func: function): {[index: string]: any}
- Gets a list of upvalues and that a function has.
local a, b, c = 1, 2, 3
local f = function() print(a, b, c) end
PrintTable(debug.getupvalues(f))
-- prints: {"a" = 1, "b" = 2, "c" = 3}
debug.typestack(count?: number): string
- Fetches a list of the current stack memory.
- This is used to debug and print out what it looks like.
debug.getstack(index: number): any
- Fetchs directly from the lua stack.
- This can be used to get values in stack memory.
debug.setstack(index: number, data: any)
- Sets a value at an index in stack memory.
- Warning: this is rather dangerous and can poison the lua stack.
#
CAPI
L:registry()
- Gets the true debug registry table, pushing it onto the stack.
- This table is used to keep permanent objects, preventing GC from removing them.
L:global()
- Gets the true global table, pushing it onto the stack.
L:env()
- Gets the current stack's environment, pushing it onto the stack.
L:getgc()
- Gets the garbage collector table, pushing it onto the stack.
- Do note this contains every value in existance.
L:newcclosure(index: number)
- Creates a new cfunction closure which is untraceable.
L:newcclosure(index: number)
- Creates a new cfunction closure which is untraceable.
L:clone(index: number)
- Copys a value in memory, creating a completely new value but with the same characteristics.
L:replace(target: number, value: number)
- Replaces a value by reference in memory, effectively replacing all occurences of it.
L:topointer(index: number, str: boolean): string | number
- Converts a datatype into it's absolute pointer location.
- Output looks like this:
"0xd8ad9caa"
or3635244450
L:frompointer(ptr: number)
- Scans memory to find the pointer association, pushing it onto the stack.