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) --]]