public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* detect empty functions
@ 2014-02-05 13:30 Prathamesh Kulkarni
  2014-02-05 14:03 ` vijay nag
  2014-02-06 11:40 ` Nicholas Mc Guire
  0 siblings, 2 replies; 11+ messages in thread
From: Prathamesh Kulkarni @ 2014-02-05 13:30 UTC (permalink / raw)
  To: gcc-help

Hi, is there a way to find if a function has empty body ?

Thanks and Regards,
Prathamesh

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 13:30 detect empty functions Prathamesh Kulkarni
@ 2014-02-05 14:03 ` vijay nag
  2014-02-05 14:03   ` vijay nag
  2014-02-06 11:40 ` Nicholas Mc Guire
  1 sibling, 1 reply; 11+ messages in thread
From: vijay nag @ 2014-02-05 14:03 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

Hello,

You can use the below program to find the length of the function
compiled for X86 target.

Note that assembly instruction for "function()" is immediately
followed by assembly for "functionEnd"

Key things to note here

1) Compiler still emits epilogue/prologue for a function with empty
body. However you could disable this using -fomit-frame-ptr in which
case function
    body will only have "ret" instruction and in which case difference
would be 1.
    0x80483a4 <function>            ret

                                   │
   │0x80483a5 <functionEnd>         ret

   So size of the function would be 0x80483a5 - 0x80483a4 = 1

 2)In case if you need frame-ptr, there will be a minimum of 4
instructions and in this case difference would be 5.
    0x80483a4 <function>            push   %ebp

                                   │
   │0x80483a5 <function+1>          mov    %esp,%ebp

                                   │
   │0x80483a7 <function+3>          pop    %ebp

                                   │
   │0x80483a8 <function+4>          ret

                                   │
   │0x80483a9 <functionEnd>         push   %ebp

                                   │
   │0x80483aa <functionEnd+1>       mov    %esp,%ebp

                                   │
   │0x80483ac <functionEnd+3>       pop    %ebp

                                   │
   │0x80483ad <functionEnd+4>       ret

     So size of the function would be 0x80483a9 - 0x80483a4 = 5


cat fsize.c
#include <stdio.h>

int function(){
}

int functionEnd(){
}

int main()
{
  printf("%x\n", &functionEnd - &function);
}

vijayNag

On Wed, Feb 5, 2014 at 7:00 PM, Prathamesh Kulkarni
<bilbotheelffriend@gmail.com> wrote:
> Hi, is there a way to find if a function has empty body ?
>
> Thanks and Regards,
> Prathamesh

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 14:03 ` vijay nag
@ 2014-02-05 14:03   ` vijay nag
  2014-02-05 14:30     ` Prathamesh Kulkarni
  0 siblings, 1 reply; 11+ messages in thread
From: vijay nag @ 2014-02-05 14:03 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On Wed, Feb 5, 2014 at 7:33 PM, vijay nag <vijunag@gmail.com> wrote:
> Hello,
>
> You can use the below program to find the length of the function
> compiled for X86 target.
>
> Note that assembly instruction for "function()" is immediately
> followed by assembly for "functionEnd"
>
> Key things to note here
>
> 1) Compiler still emits epilogue/prologue for a function with empty
> body. However you could disable this using -fomit-frame-ptr in which
> case function
>     body will only have "ret" instruction and in which case difference
> would be 1.
>     0x80483a4 <function>            ret
>
>                                    │
>    │0x80483a5 <functionEnd>         ret
>
>    So size of the function would be 0x80483a5 - 0x80483a4 = 1
>
>  2)In case if you need frame-ptr, there will be a minimum of 4
> instructions and in this case difference would be 5.
>     0x80483a4 <function>            push   %ebp
>
>                                    │
>    │0x80483a5 <function+1>          mov    %esp,%ebp
>
>                                    │
>    │0x80483a7 <function+3>          pop    %ebp
>
>                                    │
>    │0x80483a8 <function+4>          ret
>
>                                    │
>    │0x80483a9 <functionEnd>         push   %ebp
>
>                                    │
>    │0x80483aa <functionEnd+1>       mov    %esp,%ebp
>
>                                    │
>    │0x80483ac <functionEnd+3>       pop    %ebp
>
>                                    │
>    │0x80483ad <functionEnd+4>       ret
>
>      So size of the function would be 0x80483a9 - 0x80483a4 = 5
>
>
> cat fsize.c
> #include <stdio.h>
>
> int function(){
> }
>
> int functionEnd(){
> }
>
> int main()
> {
>   printf("%x\n", &functionEnd - &function);
> }
>
> vijayNag
>
> On Wed, Feb 5, 2014 at 7:00 PM, Prathamesh Kulkarni
> <bilbotheelffriend@gmail.com> wrote:
>> Hi, is there a way to find if a function has empty body ?
>>
>> Thanks and Regards,
>> Prathamesh

My apologies for top-posting.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 14:03   ` vijay nag
@ 2014-02-05 14:30     ` Prathamesh Kulkarni
  2014-02-06 10:14       ` vijay nag
  2014-02-06 12:05       ` Florian Weimer
  0 siblings, 2 replies; 11+ messages in thread
From: Prathamesh Kulkarni @ 2014-02-05 14:30 UTC (permalink / raw)
  To: vijay nag; +Cc: gcc-help

On Wed, Feb 5, 2014 at 7:33 PM, vijay nag <vijunag@gmail.com> wrote:
> On Wed, Feb 5, 2014 at 7:33 PM, vijay nag <vijunag@gmail.com> wrote:
>> Hello,
>>
>> You can use the below program to find the length of the function
>> compiled for X86 target.
>>
>> Note that assembly instruction for "function()" is immediately
>> followed by assembly for "functionEnd"
>>
>> Key things to note here
>>
>> 1) Compiler still emits epilogue/prologue for a function with empty
>> body. However you could disable this using -fomit-frame-ptr in which
>> case function
>>     body will only have "ret" instruction and in which case difference
>> would be 1.
>>     0x80483a4 <function>            ret
>>
>>                                    │
>>    │0x80483a5 <functionEnd>         ret
>>
>>    So size of the function would be 0x80483a5 - 0x80483a4 = 1
>>
>>  2)In case if you need frame-ptr, there will be a minimum of 4
>> instructions and in this case difference would be 5.
>>     0x80483a4 <function>            push   %ebp
>>
>>                                    │
>>    │0x80483a5 <function+1>          mov    %esp,%ebp
>>
>>                                    │
>>    │0x80483a7 <function+3>          pop    %ebp
>>
>>                                    │
>>    │0x80483a8 <function+4>          ret
>>
>>                                    │
>>    │0x80483a9 <functionEnd>         push   %ebp
>>
>>                                    │
>>    │0x80483aa <functionEnd+1>       mov    %esp,%ebp
>>
>>                                    │
>>    │0x80483ac <functionEnd+3>       pop    %ebp
>>
>>                                    │
>>    │0x80483ad <functionEnd+4>       ret
>>
>>      So size of the function would be 0x80483a9 - 0x80483a4 = 5
>>
>>
>> cat fsize.c
>> #include <stdio.h>
>>
>> int function(){
>> }
>>
>> int functionEnd(){
>> }
>>
>> int main()
>> {
>>   printf("%x\n", &functionEnd - &function);
>> }
>>
>> vijayNag
>>
>> On Wed, Feb 5, 2014 at 7:00 PM, Prathamesh Kulkarni
>> <bilbotheelffriend@gmail.com> wrote:
>>> Hi, is there a way to find if a function has empty body ?
>>>
>>> Thanks and Regards,
>>> Prathamesh
>
> My apologies for top-posting.
I wanted to ask, is there a way to detect if a function has empty body
using GCC API ?
Sorry if I didn't phrase it correctly earlier.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 14:30     ` Prathamesh Kulkarni
@ 2014-02-06 10:14       ` vijay nag
  2014-02-06 12:05       ` Florian Weimer
  1 sibling, 0 replies; 11+ messages in thread
From: vijay nag @ 2014-02-06 10:14 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On Wed, Feb 5, 2014 at 8:00 PM, Prathamesh Kulkarni
<bilbotheelffriend@gmail.com> wrote:
> On Wed, Feb 5, 2014 at 7:33 PM, vijay nag <vijunag@gmail.com> wrote:
>> On Wed, Feb 5, 2014 at 7:33 PM, vijay nag <vijunag@gmail.com> wrote:
>>> Hello,
>>>
>>> You can use the below program to find the length of the function
>>> compiled for X86 target.
>>>
>>> Note that assembly instruction for "function()" is immediately
>>> followed by assembly for "functionEnd"
>>>
>>> Key things to note here
>>>
>>> 1) Compiler still emits epilogue/prologue for a function with empty
>>> body. However you could disable this using -fomit-frame-ptr in which
>>> case function
>>>     body will only have "ret" instruction and in which case difference
>>> would be 1.
>>>     0x80483a4 <function>            ret
>>>
>>>                                    │
>>>    │0x80483a5 <functionEnd>         ret
>>>
>>>    So size of the function would be 0x80483a5 - 0x80483a4 = 1
>>>
>>>  2)In case if you need frame-ptr, there will be a minimum of 4
>>> instructions and in this case difference would be 5.
>>>     0x80483a4 <function>            push   %ebp
>>>
>>>                                    │
>>>    │0x80483a5 <function+1>          mov    %esp,%ebp
>>>
>>>                                    │
>>>    │0x80483a7 <function+3>          pop    %ebp
>>>
>>>                                    │
>>>    │0x80483a8 <function+4>          ret
>>>
>>>                                    │
>>>    │0x80483a9 <functionEnd>         push   %ebp
>>>
>>>                                    │
>>>    │0x80483aa <functionEnd+1>       mov    %esp,%ebp
>>>
>>>                                    │
>>>    │0x80483ac <functionEnd+3>       pop    %ebp
>>>
>>>                                    │
>>>    │0x80483ad <functionEnd+4>       ret
>>>
>>>      So size of the function would be 0x80483a9 - 0x80483a4 = 5
>>>
>>>
>>> cat fsize.c
>>> #include <stdio.h>
>>>
>>> int function(){
>>> }
>>>
>>> int functionEnd(){
>>> }
>>>
>>> int main()
>>> {
>>>   printf("%x\n", &functionEnd - &function);
>>> }
>>>
>>> vijayNag
>>>
>>> On Wed, Feb 5, 2014 at 7:00 PM, Prathamesh Kulkarni
>>> <bilbotheelffriend@gmail.com> wrote:
>>>> Hi, is there a way to find if a function has empty body ?
>>>>
>>>> Thanks and Regards,
>>>> Prathamesh
>>
>> My apologies for top-posting.
> I wanted to ask, is there a way to detect if a function has empty body
> using GCC API ?
> Sorry if I didn't phrase it correctly earlier.

Hello Prathamesh,

I do not know if GCC provides one to find if a function is empty or
not. You can extend the above logic and write a function to find if a
function has body or not. I have written a small function below called
"isFuncEmpty()". This function returns true if function has no body.
Note that I'm parsing instruction op-codes and that makes it
machinedependent(__i386__ in my case).  This function works even if
frame pointers to function is omitted by the compiler. Same logic can
be extended to any other platform by parsing preamble to the function.

#include <stdio.h>

#ifdef __i386__

typedef enum X86_OPCODES {
  X86_OPCODE_PUSH_EBP = 0x55,
  X86_OPCODE_MOV_ESP_EBP = 0xe589,
  X86_OPCODE_POP_EBP = 0x5d,
  X86_OPCODE_RETURN_INS = 0xc3,
  X86_OPCODE_MAX = 0xff,
} X86_OPCODES;

int function()
{
}

int functionEnd()
{
  int a;

  printf("Function with a body\n");
}

int isFuncEmpty(void *funcAddr)
{
  //prologue 0x5de58955
   const int prologue = (X86_OPCODE_POP_EBP << 24 |
X86_OPCODE_MOV_ESP_EBP << 8 | X86_OPCODE_PUSH_EBP);
   const int epilogue =  X86_OPCODE_RETURN_INS;
   unsigned long opcode = *(unsigned long*)funcAddr;
   unsigned char nxtOpcode = *(char*)((unsigned long*)funcAddr+1);

   /*
    * if frame-ptr exists then check for epilogue/prologue seq
    * else check for ret as the first ins
    */
   return ((X86_OPCODE_RETURN_INS) == (opcode & 0xff)) ? 1
:((opcode==prologue)&&(nxtOpcode == epilogue)) ? 1 : 0;
}

#elif /*__i386__ */
int isFuncEmpty(void *funcAddr)
{
   /*add logic for any other platform and return false or assert for now */
    return 0;
}
#endif

int main()
{
  if(isFuncEmpty(&function)) {
    printf("function() is empty\n");
  } else {
    printf("function() is not empty\n");
  }
  if (isFuncEmpty(&functionEnd)) {
    printf("functionEnd() is empty\n", isFuncEmpty(&functionEnd));
  } else {
    printf("functionEnd() is not empty\n");
  }
}

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 13:30 detect empty functions Prathamesh Kulkarni
  2014-02-05 14:03 ` vijay nag
@ 2014-02-06 11:40 ` Nicholas Mc Guire
  1 sibling, 0 replies; 11+ messages in thread
From: Nicholas Mc Guire @ 2014-02-06 11:40 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On Wed, 05 Feb 2014, Prathamesh Kulkarni wrote:

> Hi, is there a way to find if a function has empty body ?
>
There might be some way with gcc - but you might also want to consider
tools that are maybe more suitable for the task like coccinelle
Here is a simple example of detecting empty functions with coccinelle

the source file:
----------------

void foo(void){
}

int bar(int x){
}

int baz(int x){
        return x+1;
}

int main(int argc, char ** argv){
        int ret=-1;
        foo();
        ret=bar(0);
        ret=baz(ret);
        return ret;
}

the cocci script for detection and reporting:
---------------------------------------------

@empty@
identifier func;
position p1;
@@

func@p1(...){
}

@script:python@
p1 << empty.p1;
fn << empty.func;
@@

print "%s:%s empty function at lines %s" % (p1[0].file,fn,p1[0].line)

running it:
-----------

and the result of executing spatch on this hello.c

hofrat@debian:/tmp$ spatch -sp_file empty.cocci hello.c
init_defs_builtins: /usr/local/share/coccinelle/standard.h
HANDLING: hello.c
hello.c:bar empty function at lines 4
hello.c:foo empty function at lines 1

Not saying that gcc cant do it somehow - but it just might not be the
right tool to use - there are open-source tools around for checking 
source-code properties that seem more suitable for your problem.

HTH

thx!
hofrat 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-05 14:30     ` Prathamesh Kulkarni
  2014-02-06 10:14       ` vijay nag
@ 2014-02-06 12:05       ` Florian Weimer
  2014-02-06 14:16         ` Prathamesh Kulkarni
  1 sibling, 1 reply; 11+ messages in thread
From: Florian Weimer @ 2014-02-06 12:05 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On 02/05/2014 03:30 PM, Prathamesh Kulkarni wrote:
> I wanted to ask, is there a way to detect if a function has empty body
> using GCC API ?

Yes, you can write a plug-in and iterate over all the basic blocks in a 
function and check if they are empty.

A function-like entity which contains no statements might still emit 
code, so you need to figure what you need exactly.

-- 
Florian Weimer / Red Hat Product Security Team

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-06 12:05       ` Florian Weimer
@ 2014-02-06 14:16         ` Prathamesh Kulkarni
  2014-02-06 14:18           ` Florian Weimer
  0 siblings, 1 reply; 11+ messages in thread
From: Prathamesh Kulkarni @ 2014-02-06 14:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc-help

On Thu, Feb 6, 2014 at 5:34 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 02/05/2014 03:30 PM, Prathamesh Kulkarni wrote:
>>
>> I wanted to ask, is there a way to detect if a function has empty body
>> using GCC API ?
>
>
> Yes, you can write a plug-in and iterate over all the basic blocks in a
> function and check if they are empty.
I was looking for a way to detect empty function at GENERIC level.
Is the following correct way to do it ?

bool
is_tree_empty_function (tree fn)
{
  tree body, kid;

  body = DECL_SAVED_TREE (fn);
  if (!body)
    return false;
  kid = TREE_OPERAND (body, 1);
  gcc_assert (kid);
  return TREE_CODE (kid) == STATEMENT_LIST && (STATEMENT_LIST_HEAD
(kid) == NULL);
}

>
> A function-like entity which contains no statements might still emit code,
> so you need to figure what you need exactly.
>
> --
> Florian Weimer / Red Hat Product Security Team

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-06 14:16         ` Prathamesh Kulkarni
@ 2014-02-06 14:18           ` Florian Weimer
  2014-02-06 14:30             ` Prathamesh Kulkarni
  0 siblings, 1 reply; 11+ messages in thread
From: Florian Weimer @ 2014-02-06 14:18 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On 02/06/2014 03:15 PM, Prathamesh Kulkarni wrote:
> On Thu, Feb 6, 2014 at 5:34 PM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 02/05/2014 03:30 PM, Prathamesh Kulkarni wrote:
>>>
>>> I wanted to ask, is there a way to detect if a function has empty body
>>> using GCC API ?
>>
>>
>> Yes, you can write a plug-in and iterate over all the basic blocks in a
>> function and check if they are empty.

> I was looking for a way to detect empty function at GENERIC level.
> Is the following correct way to do it ?

I expect it's not fully reliable because the parser will remove some 
constructs and add others.  It depends on what you're trying to achieve.

-- 
Florian Weimer / Red Hat Product Security Team

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-06 14:18           ` Florian Weimer
@ 2014-02-06 14:30             ` Prathamesh Kulkarni
  2014-02-06 16:33               ` Florian Weimer
  0 siblings, 1 reply; 11+ messages in thread
From: Prathamesh Kulkarni @ 2014-02-06 14:30 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc-help

On Thu, Feb 6, 2014 at 7:48 PM, Florian Weimer <fweimer@redhat.com> wrote:
> On 02/06/2014 03:15 PM, Prathamesh Kulkarni wrote:
>>
>> On Thu, Feb 6, 2014 at 5:34 PM, Florian Weimer <fweimer@redhat.com> wrote:
>>>
>>> On 02/05/2014 03:30 PM, Prathamesh Kulkarni wrote:
>>>>
>>>>
>>>> I wanted to ask, is there a way to detect if a function has empty body
>>>> using GCC API ?
>>>
>>>
>>>
>>> Yes, you can write a plug-in and iterate over all the basic blocks in a
>>> function and check if they are empty.
>
>
>> I was looking for a way to detect empty function at GENERIC level.
>> Is the following correct way to do it ?
>
>
> I expect it's not fully reliable because the parser will remove some
> constructs and add others.  It depends on what you're trying to achieve.
I was trying to make -Wunused-parameter not warn, if the function is
empty (since an empty function would most likely
be a stub function).
Does that sound reasonable ?

+bool
+is_tree_empty_function (tree fn)
+{
+  tree body, kid;
+
+  body = DECL_SAVED_TREE (fn);
+  if (!body)
+    return false;
+  kid = TREE_OPERAND (body, 1); // body is bind_expr
+  gcc_assert (kid);
+  return TREE_CODE (kid) == STATEMENT_LIST && (STATEMENT_LIST_HEAD
(kid) == NULL);
+}
+
 /* Possibly warn about unused parameters.  */
 void
 do_warn_unused_parameter (tree fn)
 {
   tree decl;
-
+  bool empty_function;
+
+  empty_function = is_tree_empty_function (fn);
   for (decl = DECL_ARGUMENTS (fn);
        decl; decl = DECL_CHAIN (decl))
     if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
     && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
-    && !TREE_NO_WARNING (decl))
+    && !TREE_NO_WARNING (decl) && !empty_function)
       warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
 }

>
>
> --
> Florian Weimer / Red Hat Product Security Team

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: detect empty functions
  2014-02-06 14:30             ` Prathamesh Kulkarni
@ 2014-02-06 16:33               ` Florian Weimer
  0 siblings, 0 replies; 11+ messages in thread
From: Florian Weimer @ 2014-02-06 16:33 UTC (permalink / raw)
  To: Prathamesh Kulkarni; +Cc: gcc-help

On 02/06/2014 03:30 PM, Prathamesh Kulkarni wrote:

> I was trying to make -Wunused-parameter not warn, if the function is
> empty (since an empty function would most likely
> be a stub function).
> Does that sound reasonable ?

Yes, why not.  You should add a test case and a changelog entry and post 
it to gcc-patches for review.

>
> +bool
> +is_tree_empty_function (tree fn)
> +{
> +  tree body, kid;
> +
> +  body = DECL_SAVED_TREE (fn);
> +  if (!body)
> +    return false;
> +  kid = TREE_OPERAND (body, 1); // body is bind_expr
> +  gcc_assert (kid);
> +  return TREE_CODE (kid) == STATEMENT_LIST && (STATEMENT_LIST_HEAD
> (kid) == NULL);
> +}

Not sure about the name and how general this is.

>   /* Possibly warn about unused parameters.  */
>   void
>   do_warn_unused_parameter (tree fn)
>   {
>     tree decl;
> -
> +  bool empty_function;
> +
> +  empty_function = is_tree_empty_function (fn);
>     for (decl = DECL_ARGUMENTS (fn);
>          decl; decl = DECL_CHAIN (decl))
>       if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
>       && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
> -    && !TREE_NO_WARNING (decl))
> +    && !TREE_NO_WARNING (decl) && !empty_function)
>         warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
>   }

You should call the function only if the preceding conditions aren't false.


-- 
Florian Weimer / Red Hat Product Security Team

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-02-06 16:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-05 13:30 detect empty functions Prathamesh Kulkarni
2014-02-05 14:03 ` vijay nag
2014-02-05 14:03   ` vijay nag
2014-02-05 14:30     ` Prathamesh Kulkarni
2014-02-06 10:14       ` vijay nag
2014-02-06 12:05       ` Florian Weimer
2014-02-06 14:16         ` Prathamesh Kulkarni
2014-02-06 14:18           ` Florian Weimer
2014-02-06 14:30             ` Prathamesh Kulkarni
2014-02-06 16:33               ` Florian Weimer
2014-02-06 11:40 ` Nicholas Mc Guire

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).