Hi list,

This mail is slightly off-topic because probably not FreeBSD-centric.

I've looked at the assembly code generated by GCC, but I am not able to
understand the point of every instruction.

I've written the following useless program:
% #include <string.h>
% 
% int
% main(int ac, char *av[])
% {
%         char buf[16];
% 
%         if (ac < 2)
%                 return 0;
%         strcpy(buf, av[1]);
%         return 1;
% }

Theorically, the main() function should be something like this:
%   push %ebp
%   mov %esp, %ebp
%   sub $16, %esp
%   cmp $1, 8(%ebp)
%   jle .byebye
%   mov 12(%ebp), %eax
%   push 4(%eax)
%   push -16(%ebp)
%   call strcpy
% byebye:
%   leave
%   ret

So the stack would look like this when calling strcpy() :

        |   av   |
        |   ac   |
        |   ret  |
        | old ebp| <- ebp
        [        ]
        [        ]
        [   buf  ]
        [        ]
        |  av[1] |
        |  &buf  | <- esp


On RELENG_6, with GCC 3.4.6, I get the following assembly:
% aristote# gcc -S -O vuln.c
% aristote# cat vuln.s
%         .file   "vuln.c"
%         .text
%         .p2align 2,,3
% .globl main
%         .type   main, @function
% main:
%         pushl   %ebp
%         movl    %esp, %ebp
%         subl    $24, %esp
%         andl    $-16, %esp
%         subl    $16, %esp
%         movl    $0, %eax
%         cmpl    $1, 8(%ebp)
%         jle     .L1
%         subl    $8, %esp
%         movl    12(%ebp), %eax
%         pushl   4(%eax)
%         leal    -24(%ebp), %eax
%         pushl   %eax
%         call    strcpy
%         movl    $1, %eax
% .L1:
%         leave
%         ret
%         .size   main, .-main
%         .ident  "GCC: (GNU) 3.4.6 [FreeBSD] 20060305"

While it works, it seems to waste much space on the stack :

        |   av   |
        |   ac   |
        |   ret  |
        | old ebp| <- ebp
        {        }
        {        }
        {24 bytes}
        { (buf1) }
        {        }
        {        }      # There could be more space between the two
        [        ]      # buffers because of alignment on 16 bytes.
        [16 bytes]
        [ (buf2) ]
        [        ]
        { 8 bytes}
        { (buf3) }
        |  av[1] |
        |  &buf1 | <- esp

Is someone able to explain this please?

Interestingly, if I change the buffer size from 16 to 32 bytes, buf1 is
40 bytes wide while the two others keep the same size.

I've tried with GCC 2.95.3 from ports.  Stackwise the differences are:
        - buf2 doesn't exist
        - while buf1 is still 24 bytes long, the value passed to
          strcpy() is buf1 + 8:
                % leal -16(%ebp),%eax
                % pushl %eax


I will follow up with RELENG_7 GCC 4.2.1 output.

Thank you.
Regards,
-- 
Jeremie Le Hen
< jeremie at le-hen dot org >< ttz at chchile dot org >
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to