On Fri, 30 Mar 2018 21:15:18 -0700 Andre McCurdy <[email protected]> wrote: > Arguments passed by the caller will be put on the stack before any > stack frame is created by the callee. You can argue about which way a > stack grows (up or down) but however you define it, reading past the > end of the arguments passed on the stack by the caller is never going > to read into the stack frame created by the callee, so this can't have > the intended affect.
I definitely think it's Probably Purely Superstitious, but I'm not sure about this. I seem to recall at least one environment in which consecutive parameters had increasing addresses, and local variables had addresses higher still, so that somewhere past the address of the Nth argument would be the address of a local variable. Given how many insane calling conventions there are, I can't rule it out. (I do think you're right about the compiler probably optimizing it away, although they are not always as aggressive about that as you might expect them to be.) > This is probably going to work, but if the goal is to avoid reading > more from the stack than the generic C code would do, it doesn't > succeed. I'm aware. The purpose is to (1) use the thing most expressive of intent, (2) make sure that people know that this is not expected to be portable. "__builtin_apply()" is fairly clear as to its *intent*, and is unlikely to exist in a compatible calling convention in other compilers. > The "size" parameter to __builtin_apply() seems to simply > specify how much argument data to copy from the stack frame passed > byIt is not always simple to compute the proper value for size. the > caller. Setting it to sizeof(long long) * 7 is safe (ie it will copy > at least enough data from the stack frame passed by the caller, never > less) as it covers both the corner cases where registers are long > long (such as x32) and where _no_ arguments are passed in registers > and everything needs to be copied from the stack. However, on 32bit > targets (where registers are smaller than long long) and on any > target where _some_ arguments are passed via registers, it will cause > more data to be read from the stack than the generic C code would. Yes, it will. As the documentation says: "It is not always simple to compute the proper value for size." I do think this is currently too large; specifically, it looks as though right now there's a hard limit of 6 register-sized things, and anything that takes off_t or similar types has fewer than 6 arguments. So 6 * sizeof(off_t) or so is probably actually sufficient, if that stays true, but I don't see a feature test macro for it... > e.g. on 32bit ARM where the first 4 integer arguments are passed via > registers, the optimum value for __builtin_apply() "size" in order to > pass through 1 syscall number and 6 additional register sized > arguments would be sizeof(long) * 3. That seems probable, yes. > typedef long syscall_arg_t; /* fixme: wrong for x32 */ Yes. That's the problem: There's no sane way to express "the size that you would have gotten for these arguments of unknown types", so I intentionally went with something that may well be too long, but will not be too short. > (Note in the code was compiled with -mfloat-abi=soft to avoid > __builtin_apply() needing to save and restore all floating point > registers - which doesn't affect the amount of data read from the > stack, but makes the assembler more than twice as long...). And I don't *think* any syscalls take float arguments, but I don't know that this is not only true now, but going to stay true. -s -- _______________________________________________ Openembedded-core mailing list [email protected] http://lists.openembedded.org/mailman/listinfo/openembedded-core
