On 4/22/21, Jonathan Wakely <jwakely.gcc@xxxxxxxxx> wrote: > On Thu, 22 Apr 2021 at 19:45, Peng Yu wrote: >> The man is not well written in this and is confusing. It also doesn't >> explain the underlying details. > > The manual seems quite clear regarding those options. Here is why the manpage of these 4 options is poorly written. > -fpic > Generate position-independent code (PIC) suitable for use in a shared library, The above sentence means it can be used for shared libraries or can just be used for shared library? It is ambiguous as written in this way. > if supported for the target machine. If not supported on the target machine, so what? How do I know what target machines support it? > Such code accesses all constant addresses through a global offset table (GOT). "Such code" is to give a definition of any position-independent code. Or more narrowly, just mean the code generated by this option. > The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system). If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that -fpic does not work; in that case, recompile with -fPIC instead. This is a forward reference to -fPIC. It hasn't explained what -fPIC is at this point in the manpage. > (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit.) This seems to be an incompletely mentioned list of architectures. What about other architectures? As mentioned in this thread, the upper and lower case options are no different on x86. But this can not be seen here. > Position-independent code requires special support, and therefore works only on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. > Code > generated for the IBM RS/6000 is always position-independent. So -fpic should not be specified on IBM RS/6000? Is it still a relevant architecture nowadays? It seems to be an old architecture which is not relevant nowadays. This seems to be some history text lingering on the manpage. Why not delete them from the manpage? https://en.wikipedia.org/wiki/IBM_RISC_System/6000 > When this flag is set, the macros "__pic__" and "__PIC__" are defined to 1. What these values are for? If I were to write it, I would add a clause to explain what it is for. Like "... are defined to 1, which is for blah blah." > -fPIC If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. The above description doesn't apply to -fpic. Or they equally apply to -fpic. I don't see the difference between -fpic and -fPIC up reading here. > This option makes a difference on AArch64, m68k, PowerPC and SPARC. Difference of what? It could mean on these systems, specifying this option can be different from not specifying them. Or it could mean this option has different effects on these systems. Again it is an ambiguous sentence. > Position-independent code requires special support, and therefore works only on certain machines. What special support? What certain machines? > When this flag is set, the macros "__pic__" and "__PIC__" are defined to 2. Same question. What are these for? And how they are used? > -fpie > -fPIE These options are similar to -fpic and -fPIC, but the generated position-independent code can be only linked into executables. This is also ambiguous. What does "linked into executables" mean? "shared library" can also be linked into executables? The wording choice should be reconsidered. As I understand from previous discussion. This seems to mean, to make shared library, -fpic/-fPIC should be used. To make executable -fpie/-fPIE should be used. But as it is written, it is confusing. > Usually these options are used to compile code that will be linked using the -pie GCC option. What "usual" cases are referred? > -fpie and -fPIE both define the macros "__pie__" and "__PIE__". The macros have the value 1 for -fpie and 2 for -fPIE. What are these used for? > If you want more > details, you can always go looking in the code. Also see page 15 in > https://www.akkadia.org/drepper/dsohowto.pdf The problem is not just "more details". It is the man page is poorly written. This dsohowto.pdf document does not help to answer my question of -fpic/-fPIC/-fpie/-fPIE at this moment. As it is written, "The most important recommendation is to always use -fpic or -fPIC when generating code which ends up in DSOs. " It doesn't explain what -fpic and -fPIC are, and their difference. So it does not help. > More generally, https://lwn.net/Articles/276782/ has links to a series > of great blog posts about symbol relocations and linking. > https://www.airs.com/blog/archives/549 is from the same author. Article 549 says "It turns out to be quite simple to create a PIE: a PIE is simply an executable shared library." So this also causes confusion here. The "shared library" in "Generate position-independent code (PIC) suitable for use in a shared library," actually means "shared library" that is not executable? By "executable", it means whether it can be run or not? Many .so files (see below) do have the x permission. So the word "executable" is also ambiguous? $ ls -lgG /lib/x86_64-linux-gnu/libc-2.31.so -rwxr-xr-x 1 1839792 2021/01/05-00:47:42 /lib/x86_64-linux-gnu/libc-2.31.so "To make a shared library executable you just need to give it a PT_INTERP segment and appropriate startup code." Although there is this explanation of executable afterward, it is again confusing. The following .so file also has .interp. I don't know what "startup code" specifically refers to. But it does have some startup code. However, I don't think the author means this file is an "executable". My understanding of "executable" is just something that can run. $ readelf -x .interp /lib/x86_64-linux-gnu/libc-2.31.so Hex dump of section '.interp': 0x00193f20 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux- 0x00193f30 7838362d 36342e73 6f2e3200 x86-64.so.2. $ objdump -d /lib/x86_64-linux-gnu/libc-2.31.so |grep start 26b97: 48 8b 05 a2 73 19 00 mov 0x1973a2(%rip),%rax # 1bdf40 <_dl_starting_up> 0000000000026c20 <__libc_start_main@@GLIBC_2.2.5>: 26c3a: 48 8b 15 ff 72 19 00 mov 0x1972ff(%rip),%rdx # 1bdf40 <_dl_starting_up> ... Do you see what is wrong with writeup like these? Any verbal explanation on a complex topic like is very likely to end up confusions and ambiguities. I don't know the best solution. But it seems concrete runnable examples (https://linux.xidian.edu.cn/git/xry111/pie_vs_pic is good in this regard) and explaining the disassembled results (it lacks this aspect though to understand what exactly is going on, I am not blaming it (as it is not made for this purpose), just to mention the fact) is one way to go to fully resolve these problems. Nevertheless, the manpage is poorly written even from a pure English language point of view. -- Regards, Peng