AIM for today: 

- Extract out the pointer that is being used to call the vfunc from the current 
region.
- Search it's regions to find out which subclass the pointer is actually 
pointing to.
- Make use of this information to filter out one most probable call to function 
out of all of the possible functions that can be called at that callsite.

—

PROGRESS :

- From observation, a typical vfunc call that isn't devirtualised by the 
compiler's front end looks something like this 
"OBJ_TYPE_REF(_2;(struct A)a_ptr_5(D)->0) (a_ptr_5(D))"
where "a_ptr_5(D)" is pointer that is being used to call the virtual function.

- We can access it's region to see what is the type of the object the pointer 
is actually pointing to.

- This is then used to find a call with DECL_CONTEXT of the object from the all 
the possible targets of that polymorphic call.

- The changes can be tested on refs/users/arsenic/heads/polymorphic_cal branch 
of the repository.

- I tested the changes with on the following test program ( 
https://godbolt.org/z/fqrsE1d84 )

And it successfully provided the following analysis :

```
/Users/ankursaini/Desktop/test.cpp: In member function ‘virtual int 
B::deallocate()’:
/Users/ankursaini/Desktop/test.cpp:25:13: warning: double-‘free’ of ‘b.B::ptr’ 
[CWE-415] [-Wanalyzer-double-free]
   25 |         free(ptr);
      |         ~~~~^~~~~
  ‘void test()’: events 1-2
    |
    |   35 | void test()
    |      |      ^~~~
    |      |      |
    |      |      (1) entry to ‘test’
    |......
    |   40 |     b.allocate();
    |      |     ~~~~~~~~~~~~
    |      |               |
    |      |               (2) calling ‘B::allocate’ from ‘test’
    |
    +--> ‘void B::allocate()’: events 3-4
           |
           |   19 |     void allocate ()
           |      |          ^~~~~~~~
           |      |          |
           |      |          (3) entry to ‘B::allocate’
           |   20 |     {
           |   21 |         ptr = (int*)malloc(sizeof(int));
           |      |                     ~~~~~~~~~~~~~~~~~~~
           |      |                           |
           |      |                           (4) allocated here
           |
    <------+
    |
  ‘void test()’: events 5-6
    |
    |   40 |     b.allocate();
    |      |     ~~~~~~~~~~^~
    |      |               |
    |      |               (5) returning to ‘test’ from ‘B::allocate’
    |   41 |     foo(aptr);
    |      |     ~~~~~~~~~  
    |      |        |
    |      |        (6) calling ‘foo’ from ‘test’
    |
    +--> ‘void foo(A*)’: events 7-8
           |
           |   30 | void foo(A *a_ptr)
           |      |      ^~~
           |      |      |
           |      |      (7) entry to ‘foo’
           |   31 | {
           |   32 |     printf("%d\n",a_ptr->deallocate());
           |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |           |
           |      |           (8) calling ‘B::deallocate’ from ‘foo’
           |
           +--> ‘virtual int B::deallocate()’: events 9-10
                  |
                  |   23 |     int deallocate (void)
                  |      |         ^~~~~~~~~~
                  |      |         |
                  |      |         (9) entry to ‘B::deallocate’
                  |   24 |     {
                  |   25 |         free(ptr);
                  |      |         ~~~~~~~~~
                  |      |             |
                  |      |             (10) first ‘free’ here
                  |
           <------+
           |
         ‘void foo(A*)’: event 11
           |
           |   32 |     printf("%d\n",a_ptr->deallocate());
           |      |     ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |           |
           |      |           (11) returning to ‘foo’ from ‘B::deallocate’
           |
    <------+
    |
  ‘void test()’: events 12-13
    |
    |   41 |     foo(aptr);
    |      |     ~~~^~~~~~
    |      |        |
    |      |        (12) returning to ‘test’ from ‘foo’
    |......
    |   45 |     foo(aptr);
    |      |     ~~~~~~~~~
    |      |        |
    |      |        (13) calling ‘foo’ from ‘test’
    |
    +--> ‘void foo(A*)’: events 14-15
           |
           |   30 | void foo(A *a_ptr)
           |      |      ^~~
           |      |      |
           |      |      (14) entry to ‘foo’
           |   31 | {
           |   32 |     printf("%d\n",a_ptr->deallocate());
           |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |           |
           |      |           (15) calling ‘B::deallocate’ from ‘foo’
           |
           +--> ‘virtual int B::deallocate()’: events 16-17
                  |
                  |   23 |     int deallocate (void)
                  |      |         ^~~~~~~~~~
                  |      |         |
                  |      |         (16) entry to ‘B::deallocate’
                  |   24 |     {
                  |   25 |         free(ptr);
                  |      |         ~~~~~~~~~
                  |      |             |
                  |      |             (17) second ‘free’ here; first ‘free’ 
was at (10)
                  |
```

—

STATUS AT THE END OF THE DAY :- 

- Extract out the pointer that is being used to call the vfunc from the current 
region. (done)
- Search it's regions to find out which subclass the pointer is actually 
pointing to. (done)
- Make use of this information to filter out one most probable call to function 
out of all of the possible functions that can be called at that call-site. 
(done)

--- 

Patch file ( prototype ) : 


Attachment: indirect_calls.patch
Description: Binary data



Thank you
- Ankur

Reply via email to