c - Getting wrong glibc function address on ARM -


i want address of function. using function names gets correct addresses on x86, both local functions , glibc functions.

but on arm, local function addresses correct, while glibc function addresses wrong.

here's simple program:

#include <stdio.h> int sum(int a, int b) {     return + b; } int main(int argc, char *argv[]) {     char buffer[32] = { '\0' };     sprintf(buffer, "cat /proc/%d/maps", getpid());     printf("sum = %p\n", sum);     printf("fopen = %p\n", fopen);     system(buffer);     return 0; }  # x-compile arm executable: $ arm-linux-gnueabihf-4.9.1-gcc -g -o misc misc.c  # debug on arm /home # ./gdb ./misc gnu gdb (gdb) 7.5.1 copyright (c) 2012 free software foundation, inc. license gplv3+: gnu gpl version 3 or later <http://gnu.org/licenses/gpl.html> free software: free change , redistribute it. there no warranty, extent permitted law.  type "show copying" , "show warranty" details. gdb configured "arm-linux". bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... reading symbols /home/misc...done. (gdb) b 16 breakpoint 1 @ 0x8534: file misc.c, line 16. (gdb) r starting program: /home/misc  sum = 0x8491 fopen = 0x835c 00008000-00009000 r-xp 00000000 00:13 1703976    /home/misc 00010000-00011000 rw-p 00000000 00:13 1703976    /home/misc 76ed9000-76fd0000 r-xp 00000000 1f:08 217        /lib/libc-2.19-2014.06.so 76fd0000-76fd7000 ---p 000f7000 1f:08 217        /lib/libc-2.19-2014.06.so 76fd7000-76fd9000 r--p 000f6000 1f:08 217        /lib/libc-2.19-2014.06.so 76fd9000-76fda000 rw-p 000f8000 1f:08 217        /lib/libc-2.19-2014.06.so 76fda000-76fdd000 rw-p 00000000 00:00 0  76fdd000-76ff7000 r-xp 00000000 1f:08 199        /lib/ld-2.19-2014.06.so 76ffb000-76ffe000 rw-p 00000000 00:00 0  76ffe000-76fff000 r--p 00019000 1f:08 199        /lib/ld-2.19-2014.06.so 76fff000-77000000 rw-p 0001a000 1f:08 199        /lib/ld-2.19-2014.06.so 7efdf000-7f000000 rw-p 00000000 00:00 0          [stack] ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]  breakpoint 1, main (argc=1, argv=0x7efffe64) @ misc.c:16 16      misc.c: no such file or directory. (gdb) p fopen $1 = {<text variable, no debug info>} 0x76f26a50 <fopen> (gdb)  

note glibc text segment mapped address 76ed9000, how fopen @ wired address 0x835c?

however, next line, (gdb) p fopen, gdb gives correct address.

there no guarantee value of pointer gives in-memory address of thing you're looking for. function pointers more not have different values.

below overdid it, shame delete explanation. here's short version: function pointers guarantee comparison function pointer compare equal, complicated fast when shared libraries involved.

what's going on here has dynamic linking. when you're linking program linker doesn't know libc located in memory, can resolved dynamic linker @ runtime. naive way rewrite addresses of functions in code of program, inefficient since mean every execution of program unable share memory of executable other runs. instead called plt exists. when function call dynamically linked function actual code runs jump local function in program loads actual address of function table , jumps (this different on different architectures, general idea).

i built program on amd64, let's see in action:

(gdb) break system breakpoint 1 @ 0x400510 (gdb) run starting program: /home/art/./foo sum = 0x400660 fopen = 0x400550 [...] 

so can see on amd64 value of fopen suspicious. let's see code lurks @ address:

(gdb) x/i 0x400550    0x400550 <fopen@plt>:    jmpq   *0x200aea(%rip)        # 0x601040 <fopen@got.plt> 

first thing can notice gdb knows isn't fopen particular spot in memory called fopen@plt. , it's 1 instruction: jump value of pointer @ instruction pointer plus 0x200aea (linux/amd64 addressing relative instruction pointer) gdb nicely tells address 0x601040 , happens named fopen@got.plt. got stands global offset table , plt stands procedure linkage table.

let's go down rabbit hole:

(gdb) x/g 0x601040 0x601040 <fopen@got.plt>:   0x0000000000400556 (gdb) x/i 0x0000000000400556    0x400556 <fopen@plt+6>:  pushq  $0x5 (gdb)    0x40055b <fopen@plt+11>: jmpq   0x4004f0 (gdb) x/i 0x4004f0    0x4004f0:    pushq  0x200b12(%rip)        # 0x601008 (gdb)    0x4004f6:    jmpq   *0x200b14(%rip)        # 0x601010 (gdb) x/g 0x601010 0x601010:   0x00007ffff7df0290 (gdb) x/i 0x00007ffff7df0290    0x7ffff7df0290 <_dl_runtime_resolve>:    sub    $0x78,%rsp (gdb) 

something weird happens here. address in fopen@got.plt 1 instruction after fopen@plt, pushes on stack , jumps other code pushes more stack , jumps weird address table ends @ _dl_runtime_resolve. what's going on lazy binding. developers of dynamic linker figured out of linking information dynamic libraries , programs contain never used. when run program calls 2 function libc don't want resolve thousands , thousands of dynamic function calls libc internally, it's waste of time. also, value quick startup on quick runtime programs. default functions aren't resolved. resolved @ runtime, first time call them. that's _dl_runtime_resolve does. pushes stack non-standard way of passing arguments function because code not allowed use registers (the calling code thinks called fopen normally).

but wait minute. c standard says 2 function pointers should compare equal if point same function. how work if 1 of pointers program , 1 comes dynamic library? well, architecture dependent, after digging found on architecture when library returns function pointer, function pointer gets translated plt function in main program. why? don't know. made decision implement way @ point.


Comments

Popular posts from this blog

sql - VB.NET Operand type clash: date is incompatible with int error -

SVG stroke-linecap doesn't work for circles in Firefox? -

python - TypeError: Scalar value for argument 'color' is not numeric in openCV -