6 ms·
The Linux kernel uses a macro called RELOC_HIDE to stop gcc from seeing through the conversion from pointer to integer in these cases: https://elixir.bootlin.co
by cesarb 8y ago
The Linux kernel uses a macro called RELOC_HIDE to stop gcc from seeing through the conversion from pointer to integer in these cases: https://elixir.bootlin.com/linux/v4.18/source/include/linux/compiler-gcc.h#L50 https://elixir.bootlin.com/linux/v4.18/source/include/linux/...
Edit: a good explanation of that macro is at http://lists.linuxcoding.com/kernel/2006-q3/msg17979.html http://lists.linuxcoding.com/kernel/2006-q3/msg17979.html :
"The reason for it is that gcc assumes that if you add something on to the address of a symbol, the resulting address is still inside the bounds of the symbol, and do optimizations based on that. The RELOC_HIDE macro is designed to prevent gcc knowing that the resulting pointer is obtained by adding an offset to the address of a symbol. As far as gcc knows, the resulting pointer could point to anything."
- chrisseaton 8y ago> gcc assumes that if you add something on to the address of a symbol, the resulting address is still inside the bounds of the symbol How can one C object span two symbols in the first place for this assumption to be invalid?
- 21 8y agoIf I understand correctly what this is about, one example is buffer overflows, where you write to the first symbol but end up in the second: char symbolA[10]; char symbolB[10]; symbolA[15] = 0; // actually writes to symbolB
- chrisseaton 8y agoThis isn't one C object spanning two symbols - it's two C objects, and reading one object from a pointer to another object.
- Sharlin 8y agoHm? The point is that compilers are allowed to assume that a pointer to x can never be formed by offseting a pointer to y (except if they are subobjects in the same array). But of course you’re not prevented from trying, either on purpose or accidentally, it just results in undefined behavior.
- chrisseaton 8y ago> it just results in undefined behavior. Right - I'm saying that if they need this macro then their program is not a defined C program in the first place. They should fix that, rather than trying to use a macro to work around the problem. The macro may break in the future if GCC adds other optimisations. They call it a 'miscompilation' - how can you 'miscompile' something which is undefined!
- Sharlin 8y agoBeing pragmatic and in the OS kernel business, they basically disagree with the standard here and say that tricks like that are necessary in kernel development (even if they might not be needed in the userland). Those parts of the kernel intrinsically cannot be portable anyway. From that perspective GCC is ”wrong” if it doesn’t at least provide an ”escape hatch” to disable optimizations in cases UB isn’t UB but in fact perfectly well-defined on that particular architecture.
- deleted 8y ago[deleted]
- toast0 8y agoInsisting that the environment matches the tooling seems backwards. The tooling needs to match the needs of the environment. That GCC may break your program in the future is one of the ways that people get locked into specific versions.
- chrisseaton 8y agoYou're making it sound like the C language has changed - it hasn't. I think this operation has been undefined in C as long as Linux has existed. They should not have written that code in the first place - it was never correct.
- wruza 8y ago
- nebulous1 8y agoWhat does this have to do with "one C object span[ing] two symbols"? I'm not sure I get what you're asking
- chrisseaton 8y agoThe problem that they are solving with their macro is that > gcc assumes that if you add something on to the address of a symbol, the resulting address is still inside the bounds of the symbol I'm asking - how can you write a valid C program which adds something on to the address of a valid symbol and get something outside the bounds of the symbol?
- nebulous1 8y agoAh, now I understand. I am guessing here, but my guess is that they're using C but actually want to do something very low level. As in they believe (correctly?) that they know the exact memory layout relative to something.
- realo 8y agoCorrect. Think control/data registers in some dedicated chip.
- tom_ 8y agochar x[N],*p=x+sizeof x;
- chrisseaton 8y agoYou've defined a pointer p, but you aren't actually using it, so what's the point of that? Reading or writing the pointer p will not be a valid C program.
- tom_ 8y agoThe question appeared to be simply how one might obtain such an address.
- amluto 8y ago> How can one C object span two symbols in the first place for this assumption to be invalid? Because Linux isn’t written in C. It’s written in C, assembler, and linker script (.lds). In both assembly and linker script, one can lay out multiple symbols with a defined relationship. Unfortunately, C doesn’t have a way to say “give me a pointer to the object 10 bytes past the address p. Yes, I know it’s valid and it is not the same object as p.”