Closed maoenpei closed 4 years ago
@kubo , does this change seem reasonable to you? plthook is powerful, we really would like to contribute to its robustness and keep improve it.
@kubo Hi Kubo, I have more changes for plthook library. This library is really useful and I've met different issues while using it. The rest changes are about:
@maoenpei Sorry for my late reply.
Such library can be made by compiling one obj file with "-fPIC" but another without, and finally link them together.
I could not reproduce it. I have tested it on Ubuntu 14.04 (gcc 4.8.4), Ubuntu 16.04 (gcc 5.4.0) and Ubuntu 19.04 (gcc 8.3.0). Could you post your environment?
I made a test program and put it on gist. When a same symbol is in both PLT and GOT, it should be found twice while iterating by plthook_enum
. However it is found only once as follows.
$ wget https://gist.github.com/kubo/e456246df93b4cc95c9e47e9c3db8835/archive/7b147be9436a2b6860ee67d8463bae3b35ba030c.zip
$ unzip 7b147be9436a2b6860ee67d8463bae3b35ba030c.zip
$ cd e456246df93b4cc95c9e47e9c3db8835-7b147be9436a2b6860ee67d8463bae3b35ba030c/
$ make check
cc -c -o main.o main.c
cc -c addone_no_pic.c -fno-pic
cc -c addone_pic.c -fPIC
cc -c -o plthook_elf.o plthook_elf.c
cc -shared -o libaddone.so libaddone.c
cc -o prog main.o addone_no_pic.o addone_pic.o plthook_elf.o -L. -laddone -Wl,-rpath,'$ORIGIN' -ldl
====================================
./prog
call from pic: 11
call from no_pic: 11
0x7f7024866650:addone
====================================
objdump -d prog | grep '<addone_.*:' -A10
0000000000400e53 <addone_no_pic>:
400e53: 55 push %rbp
400e54: 48 89 e5 mov %rsp,%rbp
400e57: 48 83 ec 10 sub $0x10,%rsp
400e5b: 89 7d fc mov %edi,-0x4(%rbp)
400e5e: 8b 45 fc mov -0x4(%rbp),%eax
400e61: 89 c7 mov %eax,%edi
400e63: e8 08 fd ff ff callq 400b70 <addone@plt>
400e68: c9 leaveq
400e69: c3 retq
0000000000400e6a <addone_pic>:
400e6a: 55 push %rbp
400e6b: 48 89 e5 mov %rsp,%rbp
400e6e: 48 83 ec 10 sub $0x10,%rsp
400e72: 89 7d fc mov %edi,-0x4(%rbp)
400e75: 8b 45 fc mov -0x4(%rbp),%eax
400e78: 89 c7 mov %eax,%edi
400e7a: e8 f1 fc ff ff callq 400b70 <addone@plt>
400e7f: c9 leaveq
400e80: c3 retq
====================================
@kubo Thanks for reply. Here's a test to build an executable with both PLT and GOT, I've put source code / makefile / built binary in it: https://raw.githubusercontent.com/maoenpei/UploadFiles/master/hello.tar.gz
I'm using ubuntu 1604.
"g++ --version" g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
"readelf -r hello.out" Relocation section '.rela.dyn' at offset 0x450 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000600ff0 000300000006 R_X86_64_GLOBDAT 0000000000000000 \_gmon_start__ + 0 000000600ff8 000600000006 R_X86_64_GLOB_DAT 00000000004004f0 dlopen@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x480 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000601018 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0 000000601020 000600000007 R_X86_64_JUMP_SLO 00000000004004f0 dlopen@GLIBC_2.2.5 + 0
Thanks! It seems that he key point is assignment of function to local variables. I'll make a test program and then merge your code.
@kubo Forgot to mention, please don't add test for "plthook_enum" in this version, I'm going to pull new request that optimizes the searching progress with a hash table, and "plthook_enum" will be removed. I'm not familiar with github so I don't know if it is safe to pull requests before this change is merged.
Feel free to view my change in my forked version "https://github.com/maoenpei/plthook". I've passed your test with only "test_plthook_enum" commented out.
And of course, feel free to leave comments about the optimization. My purpose is to finally unify plthook in your github and that in my project. There are some more fixes (besides hash table change) I've made in my project. And my project is really performance sensitive so I cannot use unoptimized version.
Good luck :)
@kubo Sorry I've pushed a new commit to master branch of my forked repository, as I'm not very familiar with github mechanism. Do you need me to undo my last change? Or this time review them together? You see, I'd like all my changes be part of your repository eventually so I won't sync your changes manually.
@maoenpei Sorry for my too late reply again. I have tried to make test cases which fails without your patch several times with no luck. I concluded that there are no need to hook a GOT entry when the corresponding PLT entry is hooked. So I don't merge this PR.
The followings uses hello.out you created.
$ readelf -r hello.out
Relocation section '.rela.dyn' at offset 0x450 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600ff0 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600ff8 000600000006 R_X86_64_GLOB_DAT 00000000004004f0 dlopen@GLIBC_2.2.5 + 0
Relocation section '.rela.plt' at offset 0x480 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601018 000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000601020 000600000007 R_X86_64_JUMP_SLO 00000000004004f0 dlopen@GLIBC_2.2.5 + 0
The PLT entry is at 0x601020
. The GOT entry is at 0x600ff8
.
$ gdb -q hello.out
Reading symbols from hello.out...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x40060a
(gdb) run
Starting program: /home/kubo/Public/winshare/plthook/hello/hello.out
Breakpoint 1, 0x000000000040060a in main ()
(gdb) x/1gx 0x600ff8
0x600ff8: 0x00000000004004f0
Function calls using the GOT entry jump to 0x00000000004004f0
.
(gdb) disassemble 0x00000000004004f0
Dump of assembler code for function dlopen@plt:
0x00000000004004f0 <+0>: jmpq *0x200b2a(%rip) # 0x601020
0x00000000004004f6 <+6>: pushq $0x1
0x00000000004004fb <+11>: jmpq 0x4004d0
End of assembler dump.
The function at 0x00000000004004f0
is dlopen@plt
jumping to the address at 0x601020
, which is the address of the PLT entry. Therefore function calls using the GOT entry jump to the address in the hooked PLT entry after all when the PLT entry is hooked and the GOT entry isn't.
Hi kubo, thanks for your code that helps me to hook symbols on Linux. However I've met an issue that it will miss hooking a symbol if that symbol exists in both PLT and GOT. Such library can be made by compling one obj file with "-fPIC" but another without, and finally link them together.