Skip to content

Commit 3f562df

Browse files
committed
Add devel/scan-vtables (Linux-only, squashed)
1 parent 8e9d040 commit 3f562df

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

devel/scan-vtables.lua

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
memscan = require('memscan')
2+
3+
local df_ranges = {}
4+
for i,mem in ipairs(dfhack.internal.getMemRanges()) do
5+
if mem.read and (
6+
string.match(mem.name,'/dwarfort%.exe$')
7+
or string.match(mem.name,'/dwarfort$')
8+
or string.match(mem.name,'/Dwarf_Fortress$')
9+
or string.match(mem.name,'Dwarf Fortress%.exe')
10+
or string.match(mem.name,'/libg_src_lib.so$')
11+
)
12+
then
13+
table.insert(df_ranges, mem)
14+
end
15+
end
16+
17+
function is_df_addr(a)
18+
for _, mem in ipairs(df_ranges) do
19+
if a >= mem.start_addr and a < mem.end_addr then
20+
return true
21+
end
22+
end
23+
return false
24+
end
25+
26+
for _, range in ipairs(df_ranges) do
27+
if (not range.read) or range.write or range.execute or range.name:match('g_src') then
28+
goto next_range
29+
end
30+
31+
local area = memscan.MemoryArea.new(range.start_addr, range.end_addr)
32+
for i = 1, area.uintptr_t.count - 1 do
33+
local vtable = area.uintptr_t:idx2addr(i)
34+
local typeinfo = area.uintptr_t[i - 1]
35+
if is_df_addr(typeinfo + 8) then
36+
local typestring = df.reinterpret_cast('uintptr_t', typeinfo + 8)[0]
37+
if is_df_addr(typestring) then
38+
local vlen = 0
39+
while is_df_addr(vtable + (8*vlen)) and is_df_addr(df.reinterpret_cast('uintptr_t', vtable + (8*vlen))[0]) do
40+
vlen = vlen + 1
41+
break -- for now, any vtable with one valid function pointer is valid enough
42+
end
43+
if vlen > 0 then
44+
local ok, name = pcall(function()
45+
return memscan.read_c_string(df.reinterpret_cast('char', typestring))--:gsub('^%d+', '')
46+
end)
47+
if not ok then
48+
else
49+
local demangled_name = dfhack.internal.cxxDemangle('_Z' .. name)
50+
if demangled_name and not demangled_name:match('[<>]') and not demangled_name:match('^std::') then
51+
print(("<vtable-address name='%s' value='0x%x'/>"):format(demangled_name, vtable))
52+
end
53+
end
54+
end
55+
end
56+
end
57+
58+
end
59+
::next_range::
60+
end

0 commit comments

Comments
 (0)