[llvm-bugs] [Bug 46364] New: .init section incorrectly filled (padded) with int3 instructions

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Jun 17 08:25:54 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=46364

            Bug ID: 46364
           Summary: .init section incorrectly filled (padded) with int3
                    instructions
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: tad.coburn at sonos.com
                CC: llvm-bugs at lists.llvm.org, smithp352 at googlemail.com

Created attachment 23622
  --> https://bugs.llvm.org/attachment.cgi?id=23622&action=edit
.tar.gz file with two source files, a Makefile, and the .o and executable files
I produced locally

Environment:
Ubuntu 18.04 LTS
gcc 7.5.0
gnu make 4.1
lld-9

I am trying to use lld as a drop-in replacement for ld to speed up our builds.
The code is compiled using gcc 7.5.0. When linked using lld, the resulting
executables abort on startup with a SIGTRAP; the same exact code linked with ld
runs fine.

Repro steps:
    untar attached tar file into the current directory (3 files; one is .s with
code in the .init segment)
    # tar xzvf ld-vs-lld-init-section-crash.tar.gz
    # make clean all
    # ./myprog-ld
    OPENSSL_ia32cap_P = 0x422
    # ./myprog-ldd
    Trace/breakpoint trap (core dumped)

Expected Result:
    OPENSSL_ia32cap_P = 0x422

Actual Result:
    Trace/breakpoint trap (core dumped)

More Info:
It appears the problem has to do with fill bytes in the middle of the .init
section.  I link my test program once with ld (myprog-ld) and again using lld
(myprog-lld).

The attached .tar.gz file contains the .o and executable files I generated
locally so you can inspect them yourself with objdump.  

Here is what I found:

# objdump -d --section=".init" myprog-ld

00000380 <_init>:
 380:   53                      push   %ebx
 381:   83 ec 08                sub    $0x8,%esp
 384:   e8 b7 00 00 00          call   440 <__x86.get_pc_thunk.bx>
 389:   81 c3 4f 1c 00 00       add    $0x1c4f,%ebx
 38f:   8b 83 1c 00 00 00       mov    0x1c(%ebx),%eax
 395:   85 c0                   test   %eax,%eax
 397:   74 05                   je     39e <_init+0x1e>
 399:   e8 5a 00 00 00          call   3f8 <__gmon_start__ at plt>
 39e:   66 90                   xchg   %ax,%ax    <=== ld fills with an
executable instruction
 3a0:   e8 98 01 00 00          call   53d <OPENSSL_cpuid_setup>
 3a5:   eb 09                   jmp    3b0 <_init+0x30>
 3a7:   89 f6                   mov    %esi,%esi
 3a9:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
 3b0:   83 c4 08                add    $0x8,%esp
 3b3:   5b                      pop    %ebx
 3b4:   c3                      ret    


# objdump -d --section=".init" myprog-lld
00001220 <_init>:
    1220:       53                      push   %ebx
    1221:       83 ec 08                sub    $0x8,%esp
    1224:       e8 04 ff ff ff          call   112d <__x86.get_pc_thunk.bx>
    1229:       81 c3 cb 0e 00 00       add    $0xecb,%ebx
    122f:       8b 83 f0 ff ff ff       mov    -0x10(%ebx),%eax
    1235:       85 c0                   test   %eax,%eax
    1237:       74 05                   je     123e <_init+0x1e>
    1239:       e8 52 00 00 00          call   1290 <__gmon_start__ at plt>
    123e:       cc                      int3        <==== lld fills with int3
    123f:       cc                      int3   
    1240:       e8 ec fe ff ff          call   1131 <OPENSSL_cpuid_setup>
    1245:       eb 09                   jmp    1250 <_init+0x30>
    1247:       89 f6                   mov    %esi,%esi
    1249:       8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi
    1250:       83 c4 08                add    $0x8,%esp
    1253:       5b                      pop    %ebx
    1254:       c3                      ret    

I see that a change was made in lld-6.0 (or earlier?) to change the default
fill from 0x00 to 0xcc.  I think that is fine in general, but is incorrect for
fill bytes _in the middle_ of an .init section (and probably a .fini section as
well).

The real-world context for this is that I have a number of executables that
statically link with libcrypto.a (OpenSSL v0.9.8); that is where the assembly
code for the .init section comes from.  The OpenSSL team recommends linking
with -Bsymbolic but that has no effect when linking statically.

I was able to work around the problem by completely replacing the linker script
with a new one that with the .init section fillexp explicitly set to
0x90909090, but IMHO that should not be necessary to produce a working
executable.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200617/3e91c39c/attachment.html>


More information about the llvm-bugs mailing list