llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.03k stars 11.96k forks source link

[BOLT][X86] After optimizing with llvm-bolt, libc.so.6 encounters a runtime error. #63069

Open llongint opened 1 year ago

llongint commented 1 year ago

Error information:

./install/bin/llvm-bolt /data/rpm/new/test/lib64/libc.so.6 -o libc.so.6.bolt

image

In the code logic, determine whether the relocation item belongs to .rela.plt or .rela.dyn by the following judgment.

const bool IsJmpRel = IsJmpRelocation.contains(Rel.Type);

image

Surprisingly, the .rela.dyn section also contains a relocation entry of R_X86_64_IRELATIV (relocating to the .data.rel.ro section), which caused the section to exceed its expected size when added to .rela.plt.

llvmbot commented 1 year ago

@llvm/issue-subscribers-bolt

llongint commented 1 year ago

This error can be fixed in the following way:

diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 1c0c68c4cdfe..1f903df8f091 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -5395,6 +5396,8 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
     Offset += sizeof(*RelA);
   };

+  // Regex object for matching .data section.
+  Regex GotSection(".*\\.got(\\..)?");
   auto writeRelocations = [&](bool PatchRelative) {
     for (BinarySection &Section : BC->allocatableSections()) {
       const uint64_t SectionInputAddress = Section.getAddress();
@@ -5431,7 +5434,7 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
         NewRelA.r_offset = RelOffset;
         NewRelA.r_addend = Addend;

-        const bool IsJmpRel = IsJmpRelocation.contains(Rel.Type);
+        bool IsJmpRel = IsJmpRelocation.contains(Rel.Type) && GotSection.match(Section.getName());
         uint64_t &Offset = IsJmpRel ? RelPltOffset : RelDynOffset;
         const uint64_t &EndOffset =
             IsJmpRel ? RelPltEndOffset : RelDynEndOffset;
llongint commented 1 year ago

There are still runtime issues after this fix, and I can reproduce it in this way:

llvm-bolt /mnt/sdc/lib64/libc.so.6 -o /mnt/sdc/lib64/libc.so.6.bolt -funcs=__vfprintf_internal/1 --asm-dump
llongint commented 1 year ago

__vfprintf_internal-1.s.txt