Re: [RFC v0 0/4] Give a type to constants too

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Linus,

On 16 March 2017 at 18:40, Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, Mar 16, 2017 at 11:24 AM, Dibyendu Majumdar
> <mobile@xxxxxxxxxxxxxxx> wrote:
>>
>> Agreed and we are doing that except that the function call instruction
>> only has the type of the call, not the arguments (as far as I
>> understand - apologies if I have got this wrong).
>
> The "OP_CALL" should have the call type in the instruction itself:
>
>                 struct /* call */ {
>                         pseudo_t func;
>                         struct pseudo_list *arguments;
>                         struct symbol *fntype;
>                 };
>
> in that "fntype".
>
> So you should not need it for the pseudo (that contains the address of
> the function to call).
>

Yes, the function type is available, and this is used.

> In particular, it's not uncommon to have auto-generated code (or
> various handwritten interpreters) have the function be encoded as some
> kind of void pointer, and then depending on use, the same pointer
> value is used differently.
>
> Eg code like this:
>
>     typedef int (*binop_t)(int, int);
>     typedef int (*unop_t)(int);
>
>     #define BINOP 0
>
>     unsigned int execute(int type, void *fn, int arg1, int arg2)
>     {
>         if (type == BINOP)
>                 return ((binop_t)fn)(arg1,arg2);
>         return ((unop_t)fn)(arg1);
>     }
>
> which will linearize to something that does:
>
>     call.32     %r7 <- %r6, %arg3, %arg4
>
> in one branch, and
>
>     call.32     %r13 <- %r6, %arg3
>
> in another. Notice how it uses the same pseudo (%r6) in both cases,
> even though the type of the function called is different.
>

The issue is not with the type of %r6 but %arg3 and %arg4 if these
happen to be integer constants, and the function is variadic so we
cannot work out the type from the function prototype.

Here is a contrived example:

extern void concat(char *buf, unsigned long long len, ...);
#define NULL ((void *)0)
int main(void)
{
 char temp[256];
 concat(temp, sizeof temp, "hello", "world", NULL);
 return 0;
}

The linearized output is:

main:
.L0:
        <entry-point>
        symaddr.64  %r1 <- temp
        symaddr.64  %r2 <- <anon symbol:0000029439DF4E18>
        symaddr.64  %r3 <- <anon symbol:0000029439DF5198>
        call        concat, %r1, $256, %r2, %r3, $0
        ret.32      $0

The last argument $0 is a PSEUDO_VAL. The issue is working out what
should be the type/size of this constant.

I hope this is clearer in explaining what the problem is.

Btw the example you gave failed in sparse-llvm - because there is no
explicit cast in the linearized output. To fix it we basically have to
always cast a function to its expected type.

Thanks and Regards
Dibyendu
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux