Bug 16345 - ld emits errors on .eh_frame from partial linking
Summary: ld emits errors on .eh_frame from partial linking
Status: RESOLVED WONTFIX
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.25
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-18 21:44 UTC by Alexey Neyman
Modified: 2016-08-30 07:52 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Patch (2.16 KB, patch)
2013-12-18 21:44 UTC, Alexey Neyman
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexey Neyman 2013-12-18 21:44:25 UTC
Created attachment 7330 [details]
Patch

If ld is used to partially link several object files that have different text sections (e.g., .text and .init), the resulting object file (when used in further linking) makes ld emit an error while reading .eh_frame sections.

Test case:

$ cat qq1.s 
.text
bar: .cfi_startproc; ret; .cfi_endproc
$ cat qq2.s 
.section .init,"ax",@progbits
.globl baz
baz: .cfi_startproc; ret; .cfi_endproc
$ /home/aneyman/work/install/bin/as -o qq1.o qq1.s
$ /home/aneyman/work/install/bin/as -o qq2.o qq2.s
$ /home/aneyman/work/install/bin/ld -r -o qq.o qq1.o qq2.o
$ /home/aneyman/work/install/bin/ld -o qq -e baz qq.o
/home/aneyman/work/install/bin/ld: error in qq.o(.eh_frame); no .eh_frame_hdr table will be created.

The problem is that the code in bfd/elf-eh-frame.c assumes the relocations in the .rela.eh_frame are ordered (see GET_RELOC/SKIP_RELOCS/ENSURE_NO_RELOCS macros), but the assumption does not hold in the above scenario:

$ readelf -Wr qq.o 

Relocation section '.rela.eh_frame' at offset 0x370 contains 2 entries:
    Offset             Info             Type       Symbol's Value  Symbol's Name + Addend
0000000000000050  0000000100000002 R_X86_64_PC32  0000000000000000 .init + 0
0000000000000020  0000000200000002 R_X86_64_PC32  0000000000000000 .text + 0

The attached patch makes the code in bfd/elf-eh-frame.c fall back to slower but more resilient relocation search/check functions if it fails to interpret the .eh_frame section with the ordering assumption. Patch does not add any regressions to 'make check'.

I don't know if it would be right to sort the relocations on the output. If needed, such sorting can be added separately.
Comment 1 H.J. Lu 2013-12-20 12:51:35 UTC
.init section is a special section:

.init
    This section holds executable instructions that contribute to the process initialization code. When a program starts to run, the system arranges to execute the code in this section before calling the main program entry point (called main for C programs). 

Did you really want to use .init section here?
Comment 2 H.J. Lu 2013-12-20 13:42:00 UTC
Both .init and .fini sections are special.  This
patch warns about using "ld -r" on them:

diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 9a2fe89..098f423 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1114,7 +1114,20 @@ gld${EMULATION_NAME}_after_open (void)
     }
 
   if (link_info.relocatable)
-    return;
+    {
+      bfd *abfd;
+
+      for (abfd = link_info.input_bfds; abfd; abfd = abfd->link_next)
+	{
+	  if (bfd_get_section_by_name (abfd, ".init"))
+	    einfo ("%P: warning: -r on %B with .init section may lead"
+		   " to incorrect output.\n", abfd);
+	  if (bfd_get_section_by_name (abfd, ".fini"))
+	    einfo ("%P: warning: -r on %B with .fini section may lead"
+		   " to incorrect output.\n", abfd);
+	}
+      return;
+    }
 
   if (link_info.eh_frame_hdr
       && !link_info.traditional_format)
Comment 3 Alexey Neyman 2013-12-20 20:36:34 UTC
Well, we've been using partial linking to isolate module interfaces. One of the modules is CPU support - which includes the start-up code for the kernel. Naturally, this start up code was put into the .init section.

Our code in .init does not have .eh_frame contributions, but the mere presence of the .init section in the object file already makes `ld -r` output unsorted relocations. You can see that by substituting qq2.s in the test case with:

.section .init,"ax",@progbits
/* empty .init section */
.text
.globl baz
baz: .cfi_startproc; ret; .cfi_endproc

Now, it is probably possible for us to rename the .init section to, say, .text.startup - but are there any guarantees that `ld -r` is not going to mess up the output relocations in that case?

Also, the quote from LSB talks about semantical differences between .text and .init. Is there any technical reason not to allow `ld -r` on files with .init? Perhaps, it would be better to accept such files with unordered relocations on input and/or order the relocations on output?
Comment 4 H.J. Lu 2013-12-20 20:53:44 UTC
.init is a special section and linker treats it differently.
If you use a section name like .text.startup, it should work.
If not, please open a new linker bug report and I will fix
it.
Comment 5 Alexey Neyman 2013-12-21 01:49:17 UTC
.text.init seems to work.

You are still going to commit the patch that adds warnings for .init/.fini, correct?

Also, I think, a mention in the description of -r option in ld.info would be appropriate.
Comment 6 H.J. Lu 2013-12-21 02:10:33 UTC
(In reply to Alexey Neyman from comment #5)
> You are still going to commit the patch that adds warnings for .init/.fini,
> correct?

No.

> Also, I think, a mention in the description of -r option in ld.info would be
> appropriate.

.init section can only be used according to the gABI. It is irrelevant
to  ld -r. When in doubt, DON't USE special sections documented in the
gABI for your own purpose.
Comment 7 Alexey Neyman 2013-12-21 23:54:30 UTC
(In reply to H.J. Lu from comment #6)
> > Also, I think, a mention in the description of -r option in ld.info would be
> > appropriate.
> 
> .init section can only be used according to the gABI. It is irrelevant
> to  ld -r. When in doubt, DON't USE special sections documented in the
> gABI for your own purpose.

The .text section is also listed as a "special section" in gABI/LSB, yet you suggested to use it:

----
Special Sections
...
.init
This section holds executable instructions that contribute to the process initialization code. When a program starts to run, the system arranges to execute the code in this section before calling the main program entry point (called main for C programs).
...
.text
This section holds the ``text,'' or executable instructions, of a program.
----

I don't see how putting startup code in .init in a freestanding environment contradicts the usage described by gABI, nor why a presense of the .init section in any of the input objects should affect the relocation order in .text section. Could you explain why you think the test case is not compliant to gABI? Especially, the second version with the empty .init section?
Comment 8 H.J. Lu 2013-12-22 00:19:53 UTC
(In reply to Alexey Neyman from comment #7)
> (In reply to H.J. Lu from comment #6)
> > > Also, I think, a mention in the description of -r option in ld.info would be
> > > appropriate.
> > 
> > .init section can only be used according to the gABI. It is irrelevant
> > to  ld -r. When in doubt, DON't USE special sections documented in the
> > gABI for your own purpose.
> 
> The .text section is also listed as a "special section" in gABI/LSB, yet you
> suggested to use it:
> 
> ----
> Special Sections
> ...
> .init
> This section holds executable instructions that contribute to the process
> initialization code. When a program starts to run, the system arranges to
> execute the code in this section before calling the main program entry point
> (called main for C programs).

Linker concatenates all input .init sections and turn it into a single
function.  You can't use it for yourself.
Comment 9 Bruno De Fraine 2016-08-30 07:52:37 UTC
I also encountered the error (warning?) "no .eh_frame_hdr table will be created." when linking a relocatable object (without .init).

This bug report (and patch) discusses handling the problem of unsorted relocators at the time of final linking, when the message is raised. However, this problem was solved at partial linking in bug #17666, and that fix solved my problem.