[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