Re: What is the difference between Scrt1.o and crt1.o?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux