[PATCH 2/5] support: don't pass to resolv_test_start a big struct by value

Konstantin Kharlamov hi-angel@yandex.ru
Mon Mar 25 10:59:00 GMT 2019



On Пн, Mar 25, 2019 at 13:35:56, Florian Weimer <fw@deneb.enyo.de> 
wrote:
> * Konstantin Kharlamov:
> 
>>  On Пн, Mar 25, 2019 at 11:33:28, Florian Weimer <fw@deneb.enyo.de>
>>  wrote:
>>>  * Konstantin Kharlamov:
>>> 
>>>>   diff --git a/support/resolv_test.h b/support/resolv_test.h
>>>>   index c9e48205ab..880330ad5c 100644
>>>>   --- a/support/resolv_test.h
>>>>   +++ b/support/resolv_test.h
>>>>   @@ -116,7 +116,7 @@ void resolv_test_init (void);
>>>>       needed.  As a side effect, NSS is reconfigured to use nss_dns
>>>>  only
>>>>       for aplicable databases, and the process may enter a network
>>>>       namespace for better isolation.  */
>>>>   -struct resolv_test *resolv_test_start (struct
>>>>  resolv_redirect_config);
>>>>   +struct resolv_test *resolv_test_start (const struct
>>>>  resolv_redirect_config*);
>>> 
>>>  This patch would adjusting all the tests that call 
>>> resolv_test_start,
>>>  and these changes are missing from the patch.  It is unclear how 
>>> this
>>>  change would be an improvement because most tests call
>>>  resolv_test_start exactly once and the parameter object is never 
>>> used
>>>  again.  Passing a pointer requires writing the argument object to 
>>> the
>>>  stack *and* supplying its address to resolv_test_start, which 
>>> requires
>>>  more work.  (Maybe some targets have more optimized code for struct
>>>  initialization than passing many zero arguments, but that's a GCC
>>>  issue which will eventually be fixed.)
>> 
>>  Wow, are you saying that in the assembly the address that gets 
>> passed
>>  to resolve_test_start() would be not the address of struct, but 
>> instead
>>  an address of an addres on a stack that is an address of the 
>> struct…?
> 
> With the pointer-to-struct argument, you need to write the temporary
> object to the stack and pass its address.
> 
> With the struct argument, you need to write the temporary object to
> the stack, in the form of an argument list.
> 
> The second case avoids computing and passing the address of the
> temporary object.

Can't reproduce here. Testcase:

    $ cat test.c
    #include <stdlib.h>

    struct Foo {
        int a;
        char b;
    };

    void get_foo(struct Foo*);

    int main() {
        struct Foo foo = {};
        get_foo(&foo);
    }
    $ gcc test.c -S -fverbose-asm -o a.S -g3 -O0

Produces the following code for main() in a.S file (snip of a relevant 
part):

        .globl	main
        .type	main, @function
    main:
    .LFB6:
        .file 1 "test.c"
        .loc 1 10 12
        .cfi_startproc
        pushq	%rbp	#
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq	%rsp, %rbp	#,
        .cfi_def_cfa_register 6
        subq	$16, %rsp	#,
    # test.c:10: int main() {
        .loc 1 10 12
        movq	%fs:40, %rax	# MEM[(<address-space-1> long unsigned int 
*)40B], tmp91
        movq	%rax, -8(%rbp)	# tmp91, D.2539
        xorl	%eax, %eax	# tmp91
    # test.c:11:     struct Foo foo = {};
        .loc 1 11 16
        movq	$0, -16(%rbp)	#, foo
    # test.c:12:     get_foo(&foo);
        .loc 1 12 5
        leaq	-16(%rbp), %rax	#, tmp89
        movq	%rax, %rdi	# tmp89,
        call	get_foo@PLT	#
        movl	$0, %eax	#, _5
    # test.c:13: }

The 3 actions being done just before get_foo(), commented:

        leaq	-16(%rbp), %rax	# put address of the struct to rax register
        movq	%rax, %rdi      # move content of rax into rdi (for 
whatever reason)
        call	get_foo@PLT     # call the function

Note, it doesn't put the address into stack, it passes it in registers, 
just as I'd expect.




More information about the Libc-alpha mailing list