Giuseppe Pes
Giuseppe Pes

Reputation: 7912

Offset instruction inside program Linux

I need to find the offset of an instruction inside a program. Let's say I wanna find the position of open *system_call* in the program cat.

I used objdump to find the position inside the bin file.

objdump -T /bin/cat  | grep open : 
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fdopen
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 open
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 iconv_ope

Unfortunately, analyzing the sible table I cannot retrieve that information because the open function is linked dynamically. The open function is implemented in glibc.

Using the same approach on the Glibc library I retrieved the offset of the open function, though this offset refers to the position inside the /lib/libc.so.6 So this is not useful for me.

00000000000778d0 g    DF .text  00000000000004e3  GLIBC_2.2.5 _IO_file_fopen
000000000006be50 g    DF .text  000000000000000a  GLIBC_2.2.5 fopen
0000000000073540 g    DF .text  00000000000000f6  GLIBC_2.4   open_wmemstream
0000000000121cf0  w   DF .text  0000000000000107  GLIBC_2.2.5 posix_openpt
000000000006d480 g    DF .text  00000000000003bf  GLIBC_2.2.5 _IO_proc_open
00000000000e38b0 g    DF .text  0000000000000021  GLIBC_2.7   __open64_2
000000000006bfe0 g    DF .text  00000000000000fa  GLIBC_2.2.5 fopencookie
000000000006d840 g    DF .text  0000000000000098  GLIBC_2.2.5 popen
00000000000ddd30  w   DF .text  000000000000005e  GLIBC_2.2.5 __open64
000000000006be50 g    DF .text  000000000000000a  GLIBC_2.2.5 _IO_fopen
00000000000de020  w   DF .text  0000000000000020  GLIBC_2.7   __openat64_2
00000000000e84d0 g    DF .text  0000000000000066  GLIBC_2.2.5 openlog
00000000000ddd30  w   DF .text  000000000000005e  GLIBC_2.2.5 open64
00000000003aa630 g    DO .bss   0000000000000008  GLIBC_PRIVATE _dl_open_hook
00000000000ec840 g    DF .text  000000000000005e  GLIBC_2.14  open_by_handle_at
0000000000034250 g    DF .text  0000000000000254  GLIBC_2.2.5 catopen
000000000006d840 g    DF .text  0000000000000098  GLIBC_2.2.5 _IO_popen
0000000000075330 g    DF .text  0000000000000355  GLIBC_2.2.5 freopen64
0000000000075eb0 g    DF .text  00000000000001d8  GLIBC_2.2.5 fmemopen
00000000000b5b90  w   DF .text  000000000000008b  GLIBC_2.4   fdopendir
00000000000de020 g    DF .text  0000000000000020  GLIBC_2.7   __openat_2
00000000000b5640  w   DF .text  000000000000000d  GLIBC_2.2.5 opendir
00000000000e3880 g    DF .text  0000000000000021  GLIBC_2.7   __open_2
00000000000ddd30  w   DF .text  000000000000005e  GLIBC_2.2.5 __open
00000000000777f0 g    DF .text  00000000000000d2  GLIBC_2.2.5 _IO_file_open
0000000000074370 g    DF .text  00000000000000e6  GLIBC_2.2.5 open_memstream
0000000000073ab0 g    DF .text  000000000000035d  GLIBC_2.2.5 freopen
00000000000345a0 g    DF .text  0000000000000837  GLIBC_PRIVATE __open_catalog
00000000000ddd30  w   DF .text  000000000000005e  GLIBC_2.2.5 open
000000000006b540 g    DF .text  0000000000000249  GLIBC_2.2.5 fdopen
0000000000022b20 g    DF .text  000000000000020a  GLIBC_2.2.5 iconv_open
00000000000e2130 g    DF .text  0000000000000373  GLIBC_2.2.5 fts_open
00000000000ddf80  w   DF .text  0000000000000092  GLIBC_2.4   openat
000000000006be50  w   DF .text  000000000000000a  GLIBC_2.2.5 fopen64
00000000000ddf80  w   DF .text  0000000000000092  GLIBC_2.4   openat64
0000000000122f30 g    DF .text  0000000000000046  GLIBC_PRIVATE __libc_dlopen_mode
00000000000dc650 g    DF .text  00000000000000b8  GLIBC_2.2.5 posix_spawn_file_actions_addopen
000000000006b540 g    DF .text  0000000000000249  GLIBC_2.2.5 _IO_fdopen

I need the offset to set a tracer when the open function is called by the cat program. If I put a tracer on the Glibc lib I will trace that syscall each time it will be called.

Can you help me? Have I been clear explaining my problem?

Thanks

Upvotes: 0

Views: 662

Answers (3)

Chris Stratton
Chris Stratton

Reputation: 40347

A debugger with decent dynamic linker integration should handle this for you, resolving the symbolic name at which you wish to set a breakpoint. It can even do this when the library hasn't yet been loaded at the time you attempt to set the breakpoint.

However, be aware that there's not much of a syscall you can trace with a user-mode debugger. You can trace through the little libc stub which might do something such as re-order paramaters between the platform's C calling convention and its often different syscall convention, or implement a deprecated syscall as a wrapper around a new one, but the actual kernel mode implementation can only be traced with a kernel debugger.

You might also be interested in the strace program, which prints out the paramaters and return values of all syscalls. Another thing usefull in some cases is dynamic library interception, for example using LD_PRELOAD.

Upvotes: 1

Dmytro Sirenko
Dmytro Sirenko

Reputation: 5083

Use /proc/$PID/maps to see where a shared object library's segments are loaded in the process memory. E.g.:

# grep libc /proc/$$/maps
7f3243879000-7f3243a2e000 r-xp 00000000 08:01 270246                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3243a2e000-7f3243c2d000 ---p 001b5000 08:01 270246                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3243c2d000-7f3243c31000 r--p 001b4000 08:01 270246                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3243c31000-7f3243c33000 rw-p 001b8000 08:01 270246                     /lib/x86_64-linux-gnu/libc-2.15.so

-- so there are 4 segments of libc.so loaded into the address space of the process, we need an executable one, which is marked r-xp ("Read, no write, eXecute, Private"), its start is at *0x7f3243879000. You already know how to get relative offset for a symbols, e.g. freopen from your example is at 000000000000035d from the start of the executable segment, so in my example the symbol can be found at 7f3243879000 + 35d = *0x7f324387935d in the process memory.

Upvotes: 1

Mats Petersson
Mats Petersson

Reputation: 129344

Well, cat itself doesn't contain the open system call. It lives in glibc.so. cat calls the library to make use of the function. That's why when you look inside cat, there is no open function in it, it's "undefined" and refers to glibc.so.

You can of course find where cat calls open:

If you search for the symbol open@plt in the symbol table, that's where it calls open. For example objdump -dwhich cat|grep open@plt shows 0000000000401910 <open@plt>:, which is where the jump to the glibc function takes place.

I hope this helps.

Upvotes: 3

Related Questions