[lldb-dev] Search C++ "virtual" objects

Lei Kong via lldb-dev lldb-dev at lists.llvm.org
Mon Aug 15 16:44:26 PDT 2016

Thanks much for all the useful information!

I was able to get all vtable information with the following command, but is there an API I could use in an extension? I have checked the obvious ones “SBSymbol*”, they do not seem to have functions for iterating/searching symbols.

image lookup -A  -r -v -s "vtable"

Sent from Mail<https://go.microsoft.com/fwlink/?LinkId=550986> for Windows 10

From: Greg Clayton<mailto:gclayton at apple.com>
Sent: Friday, August 12, 2016 05:25 PM
To: Lei Kong<mailto:leikong at msn.com>
Cc: lldb-dev at lists.llvm.org<mailto:lldb-dev at lists.llvm.org>
Subject: Re: [lldb-dev] Search C++ "virtual" objects

> On Aug 12, 2016, at 4:55 PM, Lei Kong via lldb-dev <lldb-dev at lists.llvm.org> wrote:
> On Linux, given a core dump file, an executable and its symbols, is it possible to do the following in LLDB (maybe with a LLDB extension)?
> 1.       Get the list of all C++ virtual types (classes with virtual function table)

You will be able to find all vtable symbols in the symbol tables of the executable and shared libraries that you have. Not sure if the system libraries on linux have the vtable symbols in the symbol tables of the shared libraries. If you can download the separate debug info for the shared libraries that might help.

If you made a core file on your current machine and you are trying to look at this core file on the same machine without any shared libraries having been updated, then you might if the vtable symbols are in your executables in the symbol tables as you said.

So the answer is maybe. Depends on how good your symbol tables are for the executables and sharerd libraries that contain virtual classes that you care about.

> 2.       Search the whole address space to find all instances of such objects? (false positives are okay)

You should be able to iterate through all of the memory segments using:


This is a relatively new thing that was added to LLDB in the last few months so you will need a pretty recent LLDB. But this will give you all of the memory regions in your current process. You can then look at the permissions of each regions to make sure the regions is writable. So you can try this in python:

regions = lldb.process.GetMemoryRegions();
num_regions = regions.GetSize()
region = lldb.SBMemoryRegionInfo()
error = lldb.SBError()
for i in range(num_regions):
  if regions.GetMemoryRegionAtIndex(i, region):
    if region.IsWritable():
      addr = region.GetRegionBase()
      end_addr = region.GetRegionEnd()
      bytes = process.ReadMemory(addr, end_addr - addr, error)
      // Bytes is a binary python string so you can search it for the vtable pointer of your choosing

> If #1 is not possible, then how about getting virtual function table address of a given type (without an object)?

There should be symbols in the symbol tables that are the vtable symbols and you can look them up by name. For example, on MacOSX, if you compile the following:

class A
    A(int a) : m_a(a) {}
    virtual ~A() {}
    int m_a;
int main (int argc, char const *argv[], char const *envp[])
    A *a_ptr= new A(123);
    return 0;

You get a symbol table of:

(lldb) image dump symtab a.out
Symtab, file = /private/tmp/a.out, num_symbols = 19:
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      0 D   SourceFile      0x0000000000000000                    Sibling -> [   12] 0x00640000 /tmp/main.cpp
[    1]      2 D   ObjectFile      0x0000000057ae67f1                    0x0000000000000000 0x00660001 /var/folders/2y/y20b92093flcz2qdwwpf5b6c0007k2/T/main-fb7ae1.o
[    2]      4 D X Code            0x0000000100000e00 0x0000000100000e00 0x0000000000000080 0x000f0000 main
[    3]      8 D   Code            0x0000000100000e80 0x0000000100000e80 0x0000000000000030 0x001e0080 A::A(int)
[    4]     12 D   Code            0x0000000100000eb0 0x0000000100000eb0 0x0000000000000030 0x001e0080 A::A(int)
[    5]     16 D   Code            0x0000000100000ee0 0x0000000100000ee0 0x0000000000000020 0x001e0080 A::~A()
[    6]     20 D   Code            0x0000000100000f00 0x0000000100000f00 0x0000000000000030 0x001e0080 A::~A()
[    7]     24 D   Code            0x0000000100000f30 0x0000000100000f30 0x000000000000000a 0x001e0080 A::~A()
[    8]     27 D   Data            0x0000000100000f68 0x0000000100000f68 0x000000000000002c 0x000e0000 GCC_except_table0
[    9]     28 D X Data            0x0000000100000f94 0x0000000100000f94 0x0000000000000003 0x000f0080 typeinfo name for A
[   10]     29 D X Data            0x0000000100001038 0x0000000100001038 0x0000000000000020 0x001e0080 vtable for A
[   11]     30 D X Data            0x0000000100001058 0x0000000100001058 0x0000000000000010 0x000f0080 typeinfo for A
[   12]     41   X Data            0x0000000100000000 0x0000000100000000 0x0000000000000e00 0x000f0010 _mh_execute_header
[   13]     43     Trampoline      0x0000000100000f46 0x0000000100000f46 0x0000000000000006 0x00010200 _Unwind_Resume
[   14]     44   X Undefined       0x0000000000000000                    0x0000000000000000 0x00010100 vtable for __cxxabiv1::__class_type_info
[   15]     45     Trampoline      0x0000000100000f3a 0x0000000100000f3a 0x0000000000000006 0x00010180 operator delete(void*)
[   16]     46     Trampoline      0x0000000100000f40 0x0000000100000f40 0x0000000000000006 0x00010180 operator new(unsigned long)
[   17]     47   X Undefined       0x0000000000000000                    0x0000000000000000 0x00010100 __gxx_personality_v0
[   18]     48   X Undefined       0x0000000000000000                    0x0000000000000000 0x00010200 dyld_stub_binder

Note the entry for the vtable:

[   10]     29 D X Data            0x0000000100001038 0x0000000100001038 0x0000000000000020 0x001e0080 vtable for A

We can see that the load address is 0x0000000100001038 and we would look for memory regions that contains this pointer.

I am not sure if linux has a way to iterate over all of the malloc blocks in the heap. MacOSX does, but I am not sure if linux does. If it does, you might be able to replicate this block iteration from python if you can see how they do it. Barring that, you are limited to looking through all memory regions in your process for this the vtable pointer (0x0000000100001038).


> Thanks much.
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160815/f5fcc6ff/attachment-0001.html>

More information about the lldb-dev mailing list