8

.plt : in RE able segment, have trampoline functioning at plt[n] except 0, have .got.plt resolver link at plt[0]

.got .got.plt : in RW able segment, just address

Which I learned from this post: https://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

Problem

Actual Linux shell command gave me a different answer

$readelf -l /bin/bash

read elf -l result

got.plt is gone and what is .plt.got in 02 segment?

I dumped two section(plt, plt.got) and got this assembly

.plt is plt as i learned: .plt is plt as i learned

.plt.got , what is this for? .plt.got , what is this for

sorry for poor dumping, it was done by

objcopy -O binary --only-section=.plt.got /bin/bash ./pltgot
objcopy -O binary --only-section=.plt /bin/bash ./plt

Questions

  1. what is difference between .plt and .plt.got
  2. why this difference happened?
kinokijuf
  • 968
  • 1
  • 11
  • 33
noBODYcare
  • 101
  • 1
  • 6
  • 1
    Don't post pictures of text. Copy/paste your readelf output into a code block, preferably just the relevant parts. Good question other than that, but that's a big problem. – Peter Cordes Sep 26 '19 at 02:46
  • thanks for edit, i concerned just having thanks comment is also rule violating and may kill the post. but there is no answer still and i think post will drown into deep dark storage in stackoverflow. i mean.. um... thank you for your advice! i'll try to be more friendly to stackoverflow editing style. – noBODYcare Sep 27 '19 at 14:34
  • It's not too late to fix your question with your [edit]. I'd upvote it if not for the pictures of text. And BTW, you can use `objdump -d --section=.plt.got` instead of dumping it to a flat binary first. See the `-j` option in the man page. You can also use `-j` / `--section` twice in one invocation to disassemble both sections. – Peter Cordes Sep 27 '19 at 16:20
  • BTW, some modern Linux systems (e.g. Arch) compile packages with `gcc -fno-plt` so there is not `.plt` or `.plt.got` section in `/bin/bash` or other binaries. – Peter Cordes Sep 27 '19 at 16:21

2 Answers2

10

The difference between .plt and .plt.got is that .plt uses lazy binding and .plt.got uses non-lazy binding.

Lazy binding is possible when all uses of a function are simple function calls. However, if anything requires the address of the function, then non-lazy binding must be used, since binding can only occur when the function is called, and we may need to know the address before the first call. Note that when obtaining the address, the GOT entry is accessed directly; only the function calls go via .plt and .plt.got. If the -fno-plt compiler option is used, then neither .plt nor .plt.got are emitted, and function calls also directly access the GOT entry.

In the following examples, objdump -d is used for disassembly, and readelf -r is used to list relocations.

.plt

Using x64-64 as an example, .plt will contain entries such as:

0000000000014050 <_Unwind_Resume@plt>:
   14050:       ff 25 3a e6 0e 00       jmpq   *0xee63a(%rip)        # 102690 <_Unwind_Resume@GCC_3.0>
   14056:       68 02 00 00 00          pushq  $0x2
   1405b:       e9 c0 ff ff ff          jmpq   14020 <.plt>

The first jmpq is to the GOT entry, and the second jmpq performs the lazy binding if the GOT entry hasn't been bound yet.

The relocations for .plt's associated GOT entries are in the .rela.plt section and use R_X86_64_JUMP_SLOT, which lets the dynamic linker know these are lazy.

0000000000102690  0000004600000007 R_X86_64_JUMP_SLOT     0000000000000000 _Unwind_Resume@GCC_3.0 + 0

.plt.got

.plt.got contains entries that only need a single jmpq since they aren't lazy:

0000000000014060 <memset@plt>:
   14060:       ff 25 5a ea 0e 00       jmpq   *0xeea5a(%rip)        # 102ac0 <memset@GLIBC_2.2.5>
   14066:       66 90                   xchg   %ax,%ax

The relocations for .plt.got's associated GOT entries are in the .rela.dyn section (along with the rest of the GOT relocations), which the dynamic linker binds immediately:

0000000000102ac0  0000004b00000006 R_X86_64_GLOB_DAT      0000000000000000 memset@GLIBC_2.2.5 + 0
Philip Craig
  • 168
  • 1
  • 7
  • Your disassembly is from `objdump -d`, but what are the `R_X86_64_JUMP_SLOT` vs. `R_X86_64_GLOB_DAT` lines from? `readelf`, or a different option for `objdump`? – Peter Cordes Nov 11 '20 at 10:44
  • They are from `readelf`. `objdump -R` would work too, but it doesn't show which sections contains the relocations. – Philip Craig Nov 12 '20 at 06:26
  • Ok, cool. Generally it's a good idea to mention the command that generated output you show in an answer, so future readers can try it themselves. (An [edit] would be even better than just a comment.) BTW, also worth pointing out that the `.plt.got` non-lazy entries are what `gcc -fno-plt` code-gen uses, which is the default for some distros such as Arch Linux. – Peter Cordes Nov 12 '20 at 06:33
  • `-fno-plt` doesn't use `.plt.got`, so I edited the answer to cover that too. – Philip Craig Nov 12 '20 at 08:47
  • Err right, just GOT entries directly, using `R_X86_64_GLOB_DAT` like `.plt.got` does, thanks. – Peter Cordes Nov 12 '20 at 08:49
  • A little remark - for my *gcc (Debian 11.3.0-3) 11.3.0* `-fno-plt` switch doesn't stop to emit `.plt` and `.plt.got` sections. Instead, just call instructions use GOT directly, without using PLT. And the default entry inside PLT (the one which jumps to `_dl_resolve`) is the only one. – mathway Jul 12 '22 at 18:15
5

See answer to your questions. Hopefully it helps you.

  1. The difference is that .got.plt is runtime-writable, while .got is not if you enable a defense against GOT overwriting attacks called RELRO (relocations read-only). To enable RELRO, you use the ld option -z relro. RELRO places GOT entries that must be runtime-writable for lazy binding in .got.plt, and all others in the read-only .got section

  2. The difference or this design rather has been there as part of the ELF common standard file format:

    ELF binaries often contain a separate GOT section called .got.plt for use in conjunction with .plt in the lazy binding process

Q1 Ref Page 45: Andriesse, Dennis.Practical binary analysis : build your own Linux tools for binary instrumentation, analysis, and disassembly.San Francisco, No Starch Press, 2019

Q2 Ref Page 45: same book, see section "Lazy Binding and the PLT"

david
  • 77
  • 2
  • 9