|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- peek.lua - a tool to inspect C data structures from Lua
-- This was developed as part of the DaVinci project.
-- Project page: <http://angg.twu.net/davinci.html>
-- also: <http://angg.twu.net/peek.html>
-- <http://angg.twu.net/middle-c.html>
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2007aug05
-- (find-a2ps (buffer-file-name))
--- _ _ _ _ _
--- | |_ _ _ _ __ ___ | |__ _ _(_) | __| | ___ _ __ ___
--- | __| | | | '_ \ / _ \ | '_ \| | | | | |/ _` |/ _ \ '__/ __|
--- | |_| |_| | |_) | __/ | |_) | |_| | | | (_| | __/ | \__ \
--- \__|\__, | .__/ \___| |_.__/ \__,_|_|_|\__,_|\___|_| |___/
--- |___/|_|
TD = {}
newctype = function (kind, typename, sizeof, td)
td.kind = kind
td.type = typename
td.sizeof = sizeof
TD[typename] = td
PP(td)
end
BaseType = function (new, sizeof)
newctype("base", new, sizeof, {})
end
ArrayOf = function (old, new, n)
newctype("array", new, n and (n * TD[old].sizeof), {star=old})
end
PointerTo = function (old, new)
newctype("pointer", new, 4, {star=old})
end
StructOrUnion = function (kind, fielddecls, shortname, typedefedname)
local totalsize = 0
local fields = {}
local descriptions = {}
for type,varname in string.gmatch(fielddecls, "(%S+)%s+([%w_]+);?") do
local fieldsize = TD[type].sizeof
local offset = (kind=="union") and 0 or totalsize
if not fieldsize then
error(kind.." "..shortname..": type "..type.." has no sizeof")
end
table.insert(descriptions, type..":"..varname)
table.insert(fields, {type=type, name=varname, offset=offset})
fields[varname] = table.getn(fields)
totalsize = (kind=="union")
and math.max(totalsize, fieldsize)
or totalsize + fieldsize
end
---- I don't need the longnames now, and they make the dumps hard to read.
-- local longname = kind.."{"..table.concat(descriptions, ",").."}"
-- newctype(kind, longname, totalsize, {fields=fields})
if shortname then
newctype(kind, shortname, totalsize, {fields=fields})
end
if typedefedname then
newctype(kind, typedefedname, totalsize, {fields=fields})
end
end
StructOf = function (fielddecls, shortname, typedefedname)
StructOrUnion("struct", fielddecls, shortname, typedefedname)
end
UnionOf = function (fielddecls, shortname, typedefedname)
StructOrUnion("union", fielddecls, shortname, typedefedname)
end
FunctionType = function (new, arglist) -- practically a stub
newctype("function", new, nil, {})
end
smasharglist = function (arglist)
arglist = string.gsub(arglist, ",%s+", ",")
arglist = string.gsub(arglist, "%s+", ":")
return arglist
end
copy = function (tbl)
newtbl = {}
for k,v in pairs(tbl) do newtbl[k] = v end
return newtbl
end
TypedefTo = function (old, new)
if old:match("^struct:[%w_]+") or old:match("^union:[%w_]+") then
TD[new] = setmetatable({}, {
__index = function (key) return TD[old][key] end
})
else
TD[new] = copy(TD[old])
TD[new].type = new
end
end
--[[
* (eepitch-kill)
* (eepitch-lua51)
--]]
--- _
--- | | _ __ ___ __ _ ___ _ __ ___
--- | | | '_ \ / _ \/ _` | / _ \| '_ \/ __|
--- | |___| |_) | __/ (_| | | (_) | |_) \__ \
--- |_____| .__/ \___|\__, | \___/| .__/|___/
--- |_| |___/ |_|
dotower = function (basetype, boxesandstars)
PP("dotower", basetype, boxesandstars)
for _,s in ipairs(boxesandstars) do
if s == "*" then
PointerTo(basetype, basetype..s)
else
local n = tonumber(string.match(s, "%[([0-9]*)%]"))
ArrayOf(basetype, basetype..s, n)
end
basetype = basetype..s
end
end
dostructdecl = function (structtype, fielddecls)
PP("dostructdecl", structtype, fielddecls)
StructOf(fielddecls, structtype)
end
dostructdecl = function (structtype, fielddecls)
PP("dostructdecl", structtype, fielddecls)
StructOf(fielddecls, structtype)
end
douniondecl = function (uniontype, fielddecls)
PP("douniondecl", uniontype, fielddecls)
UnionOf(fielddecls, uniontype)
end
dotypedefstruct = function (structtype, fielddecls, simpletype)
PP("dotypedefstruct", structtype, fielddecls, simpletype)
StructOf(fielddecls, structtype, simpletype)
end
dotypedefunion = function (uniontype, fielddecls, simpletype)
PP("dotypedefunion", uniontype, fielddecls, simpletype)
UnionOf(fielddecls, uniontype, simpletype)
end
dotypedefbase = function (towertype, simpletype)
PP("dotypedefbase", towertype, simpletype)
TypedefTo( towertype, simpletype)
end
dotypedeffun = function (rettype, arglist, simpletype)
PP("dotypedeffun", rettype, arglist, simpletype)
funtype = rettype .. "(" .. smasharglist(arglist) .. ")"
funptrtype = funtype .. "*"
PointerTo(funtype, funptrtype)
TypedefTo(funptrtype, simpletype)
end
--- _ _
--- | | _ __ ___ __ _ _ __ __ _| |_ ___
--- | | | '_ \ / _ \/ _` | | '_ \ / _` | __/ __|
--- | |___| |_) | __/ (_| | | |_) | (_| | |_\__ \
--- |_____| .__/ \___|\__, | | .__/ \__,_|\__|___/
--- |_| |___/ |_|
--
-- (find-es "lua5" "lpeg-quickref")
loadlpeg()
-- Parsing-only versions of the patterns.
-- Not all of these are used in the final program,
-- but they are the skeletons for the versions in the
-- block below, that involve "capture"s and "do"s.
S = lpeg.S(" \t\n\r") ^ 0
Alpha = lpeg.R("AZ", "az", "__")
AlphaNum = lpeg.R("AZ", "az", "__", "09")
SimpleType = Alpha * AlphaNum ^ 0
StructType = "struct:" * SimpleType
UnionType = "union:" * SimpleType
SemiSimpleType = StructType + UnionType + SimpleType
Box = "[" * lpeg.R("09") ^ 0 * "]"
Star = lpeg.P("*")
TowerType = SemiSimpleType * (Box + Star) ^ 0
Field = S * TowerType * S * SimpleType * lpeg.P(";") ^ -1 * S
Arg = S * TowerType * S * SimpleType * lpeg.P(",") ^ -1 * S
FieldList = "{" * Field ^ 0 * "}"
ArgList = "(" * Arg ^ 0 * ")"
StructDecl = StructType * S * FieldList * ";" * S
UnionDecl = UnionType * S * FieldList * ";" * S
TypedefStruct = "typedef" * S * StructType * S * FieldList * S *
SimpleType * ";" * S
TypedefUnion = "typedef" * S * UnionType * S * FieldList * S *
SimpleType * ";" * S
TypedefBase = "typedef" * S * TowerType * S *
SimpleType * ";" * S
TypedefFun = "typedef" * S * TowerType * S * ArgList * "*" * S *
SimpleType * ";" * S
--- _ _ ____ ____
--- | | _ __ ___ __ _ _ __ __ _| |_ ___ _ / ___| _ \
--- | | | '_ \ / _ \/ _` | | '_ \ / _` | __/ __(_) | | | | | |
--- | |___| |_) | __/ (_| | | |_) | (_| | |_\__ \_ | |___| |_| |
--- |_____| .__/ \___|\__, | | .__/ \__,_|\__|___(_) \____|____/
--- |_| |___/ |_|
-- Suffixes: "C" stands for "Capture",
-- "D" stands for "Do".
-- We could have built the "D" patterns right away,
-- but if we keep also the "C" subpatterns around
-- then things become easier to understand and to debug.
SimpleTypeC = lpeg.C(SimpleType)
StructTypeC = lpeg.C(StructType)
UnionTypeC = lpeg.C(UnionType)
TowerTypeC = (lpeg.C(SemiSimpleType) * lpeg.Ct((lpeg.C(Box + Star)) ^ 0))
TowerTypeD = lpeg.C(TowerTypeC / dotower)
FieldD = S * TowerTypeD * S * SimpleType * lpeg.P(";") ^ -1 * S
ArgD = S * TowerTypeD * S * SimpleType * lpeg.P(",") ^ -1 * S
FieldListC = "{" * lpeg.C(FieldD ^ 0) * "}"
ArgListC = "(" * lpeg.C(ArgD ^ 0) * ")"
StructDeclC = StructTypeC * S * FieldListC * ";" * S
UnionDeclC = UnionTypeC * S * FieldListC * ";" * S
TypedefStructC = "typedef" * S * StructTypeC * S * FieldListC * S *
SimpleTypeC * ";" * S
TypedefUnionC = "typedef" * S * UnionTypeC * S * FieldListC * S *
SimpleTypeC * ";" * S
TypedefBaseC = "typedef" * S * TowerTypeD * S *
SimpleTypeC * ";" * S
TypedefFunC = "typedef" * S * TowerTypeD * S * ArgListC * "*" * S *
SimpleTypeC * ";" * S
StructDeclD = StructDeclC / dostructdecl
UnionDeclD = UnionDeclC / douniondecl
TypedefStructD = TypedefStructC / dotypedefstruct
TypedefUnionD = TypedefUnionC / dotypedefunion
TypedefBaseD = TypedefBaseC / dotypedefbase
TypedefFunD = TypedefFunC / dotypedeffun
DeclarationD = StructDeclD +
UnionDeclD +
TypedefStructD +
TypedefUnionD +
TypedefBaseD +
TypedefFunD
-- (find-es "lua5" "lpeg-quickref")
-- (TowerTypeC / PP):match("foo*[2][3][]")
-- TowerTypeT:match("str:foo*[2][3][]")
--- _____ _ __ _ __
--- |_ _|__ ___| |_ ___ / /___ | | _\ \
--- | |/ _ \/ __| __/ __| | |/ _ \| |/ /| |
--- | | __/\__ \ |_\__ \ | | (_) | < | |
--- |_|\___||___/\__|___/ | |\___/|_|\_\| |
--- \_\ /_/
BaseType("char", 1)
BaseType("unsignedchar", 1)
BaseType("int", 4)
BaseType("unsignedint", 4)
BaseType("long", 4)
BaseType("unsignedlong", 4)
BaseType("double", 8)
BaseType("void", nil)
dd = function (str) (DeclarationD ^ 1):match(str) end
dd [==[
typedef int ptrdiff_t;
typedef unsignedint size_t;
typedef int wchar_t;
union:luai_Cast { double l_d; long l_l; };
typedef struct:lua_State lua_State;
]==]
PP(TypedefBaseC:match [==[
typedef struct:lua_State lua_State;
]==])
dd [==[
typedef int (lua_State* L)* lua_CFunction;
typedef char* (lua_State* L, void* ud, size_t* sz)* lua_Reader;
typedef int (lua_State* L, void* p, size_t sz, void* ud)* lua_Writer;
typedef void* (void* ud, void* ptr, size_t osize, size_t nsize)* lua_Alloc;
typedef double lua_Number;
typedef ptrdiff_t lua_Integer;
typedef struct:lua_Debug lua_Debug;
typedef void (lua_State* L, lua_Debug* ar)* lua_Hook;
]==]
dd [==[
struct:lua_Debug {
int event;
char* name;
char* namewhat;
char* what;
char* source;
int currentline;
int nups;
int linedefined;
int lastlinedefined;
char[60] short_src;
int i_ci;
};
]==]
dd [==[
typedef unsignedint lu_int32;
typedef size_t lu_mem;
typedef ptrdiff_t l_mem;
typedef unsignedchar lu_byte;
typedef union:L_Umaxalign { double u; void* s; long l; } L_Umaxalign;
typedef double l_uacNumber;
typedef lu_int32 Instruction;
typedef union:GCObject GCObject;
typedef struct:GCheader {
GCObject* next; lu_byte tt; lu_byte marked;
} GCheader;
]==]
--[[
# (find-angg "LUA/lua50init.lua" "loadpeek")
* (eepitch-kill)
* (eepitch-lua51)
dofile(ee_expand("~/DAVINCI/peek.lua"))
-- **** error below
dd [==[
typedef union:Value {
GCObject* gc;
void* p;
lua_Number n;
int b;
} Value;
]==]
dd [==[
typedef union:uu {
int ii;
} uu;
]==]
dd [==[
typedef struct:lua_TValue {
Value value; int tt;
} TValue;
]==]
dd [==[
typedef TValue* StkId;
struct:TString__tsv {
GCObject* next; lu_byte tt; lu_byte marked;
lu_byte reserved;
unsigned int hash;
size_t len;
};
]==]
dd [==[
]==]
-- Tests for peek:
hexton = function (str) return tonumber(str, 16) end
gethexaddr = function (str) return string.match(str, " 0x([0-9A-Za-z]+)") end
getaddr = function (obj)
return tonumber(string.match(tostring(obj), " 0x([0-9A-Za-z]+)"), 16)
end
= getaddr(peek)
= getaddr({})
= tostring(peek)
a = getaddr(tostring(peek))
= a
= peek(a, 4)
= format("%q", peek(a, 4))
= tostring("foo")
= tostring("foo\n")
* (eepitch-gdb-lua-kill)
* (eepitch-gdb-lua)
p sizeof(double)
p sizeof(long)
* (eepitch-gdb-lua-kill)
--]]