[lldb-dev] [Reproducers] SBReproducer RFC
Pavel Labath via lldb-dev
lldb-dev at lists.llvm.org
Wed Jan 9 05:06:03 PST 2019
On 08/01/2019 21:57, Jonas Devlieghere wrote:
> Before I got around to coding this up I realized you can't take the
> address of constructors in C++, so the function address won't work as an
> identifier.
>
You gave up way too easily. :P
I realized that constructors are going to be tricky, but I didn't want
to dive into those details until I knew if you liked the general idea.
The most important thing to realize here is that for the identifier
thingy to work, you don't actually need to use the address of that
method/constructor as the identifier. It is sufficient to have something
that can be deterministically computed from the function. Then you can
use the address of *that* as the identifier.
I've created a very simple prototype <https://godbolt.org/z/_xDt5r>,
where I do just that. The way I handle constructors there is that I
create a special class template (construct), whose instantiations are
going to be unique for each constructor (I achieve that by making the
class name and the constructor argument types the template parameters of
that function). Then I can take the address of the static member
function inside this class (&construct<class, arguments...>::doit), and
use *that* as the ID.
As a nice side-effect, the "doit" method actually does invoke the
constructor in question, so I can also use that in the replay code to
treat constructors like any other method that returns an object.
I also do the same thing for (non-static) member functions via the
"invoke" template, because even though it is possible to take the
address of those, it is very hard to do anything else with the retrieved
pointer. So the effect of this that in the rest of the code, I only have
to work with free functions, as both constructors and member functions
are converted into equivalent free functions. I haven't tried to handle
destructors yet, but I don't think those should pose any problems that
we haven't encountered already.
The example also show how you can use templates to automatically
generate replay code for "simple" (i.e. those where you can
(de)serialize each argument independently) functions, and then uses that
to record/replay a very simple API.
You can see it in action like this:
$ g++ a.cc # compile
$ ./a.out 2>/tmp/recording # generate the recording
SBFoo 47 42
Method 1 2
Static 10 11
$ cat /tmp/recording
0 # ID of the constructor
47 # constructor arg 1
42 # constructor arg 2
0x7ffd74d9a0f7 # constructor result
1 # id of SBFoo::Method
0x7ffd74d9a0f7 # this
1 # arg 1
2 # arg 2
2 # id of SBFoo::Static
10 # arg 1
11 # arg 2
$ ./a.out 1 < /tmp/recording # replay the recording
SBFoo 47 42
SBFoo 42 47
Method 1 2
Static 10 11
Note that when replaying the SBFoo constructor is called twice. This is
because this code does not attempt to track the object instances in any
way... it just creates a new one each time. This obviously needs to be
fixed, but that's independent of the function ID issue.
hope you find that useful,
pl
More information about the lldb-dev
mailing list