loaderの挙動

2011/11/20Linux::ldimport

ELFセクションについて..

TEXTREL : .text内の再配置(コード書き換え)を行う. static linkerと同じことをやるってことか...

用語/単語?

もっと詳しく調べないといけない。とりあえず暫定.. PIC : Position Independent Code *.sだして, call function名 を探してみるといい. @PLTつきの呼び出しがあるくさい. (relaxと同じような効果か?)


トレース

ld-linux.so がELFファイルのローダ本体. [Mr.Dan Williams:http://www.cs.virginia.edu/~dww4s/articles/ld_linux.html]曰く、[ここ:http://www.cs.virginia.edu/~dww4s/articles/ld_linux.html]でld-linux.soのstartup部分について解説されています。

So, the files included as part of the librtld.os object are the things included in dl-allobjs.os, rtld-libc.a, as well as libgcc.so. Note the arguments -( and -) which are sent to the linker with the -Wl, prefix. Those arguments tell the linker to iterate over the archives until a steady state is reached. dl-allobjs.os and rtld-libc.a contain the object files for the shared library, along with the entry point _start. _start is defined in rtld.c, from a macro (RTLD_START) included in the header file dl-machine.h. The macro expands into inlined assembly which define the _start symbol, and calls the function _dl_start. Since ld-linux.so.2 has a _start symbol, it is able to to be run directly.

man pageを見てみると...

概要
ダイナミックリンカは、いくつか動的にリンクされたプログラムやライブラリを実行することによって
間接的に実行、
(ダイナミックリンカへのコマンドラインオプションを渡すことができないことと、
 ELFの場合には、プログラム中のセクション".interp"に保存されている動的リンカが実行されます)
 または、直接プログラムが実行される。

説明
プログラムld.soとld-linux.so*は、プログラムの実行準備し、プログラムに必要な共有ライブラリと実行するプログラムを見つけ出し、ロードし、それを実行する。
Linuxバイナリは、コンパイル時にld(1)に対して"-static"オプションを与えない限り、dunamic linking(実行時にリンクする)を要求する。
ld.soは、ずいぶん昔に使われたフォーマットのa.outバイナリをハンドリングする。
ld-linux.so*は、近年皆が使っているELFフォーマットをハンドリングする。(/lib/ld-linux.so.1 for libc5, /lib/ld-linux.so.2 for glibc2), 
どちらも同じ挙動で、同じサポートファイル(/etc/ld.so.conf)、サポートプログラム(ldd(1),ldconfig(8))を使います。

プログラムに必要なshared librariesは、以下の順に検索されます。
1. (ELF形式のみ) もしあれば、バイナリのdynamic section属性の付いたDT_RPATH内に与えられたディレクトリを使い、
	DT_RUNPATH属性が無い場合。(Use of DT_RPATH is deprecated)
2.環境変数 LD_LIBRARY_PATH を使う。ただし、set-user-ID/set-group-ID がセットされたバイナリは除く。
3.default pathである、"/lib", "/usr/lib"を探す。
ただし、リンカオプション"-z nodeflib"をつけていた場合はスキップされる。

ld.so understands the string $ORIGIN (or equivalently ${ORIGIN}) in an rpath specification
 (DT_RPATH or DT_RUNPATH) to mean the directory containing the application executable.
ld.soは、DT_RPATH or DT_RUNPATHといったrpath仕様で"$ORIGIN"または同等の"${ORIGIN}"文字列を理解する。
実行可能なアプリケーションを含むディレクトリを意味する

Thus, an application located in somedir/app could be compiled with gcc -Wl,-rpath,'$ORIGIN/../lib'
 so that it finds an associated shared library in somedir/lib no matter
  where somedir is located in the directory hierarchy.
somedir/appにおかれたアプリケーションは、gccの"-Wl,-rpath,'$ORIGIN/../lib'"オプションでコンパイルできる。
ディレクトリ階層内のsomdirに。..?


This facilitates the creation of "turn-key" applications
 that do not need to be installed into special directories,
  but can instead be unpacked into any directory and still find their own shared libraries.
これは特別なディレクトリにインストールする必要がない"ターンキー"アプリケーションの作成 ​​が容易ではなく、
任意のディレクトリに展開されると、まだ自分自身の共有ライブラリを見つけることができます。 
???


迷ったらソース読みましょう

glibc-2.11/elf/Makefile

# ld.so uses those routines, plus some special stuff for being the program
# interpreter and operating independent of libc.
rtld-routines   := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
include ../Rules

check-abi: check-abi-ld
update-abi: update-abi-ld

ifeq (yes,$(build-shared))
# Make sure these things are built in the `make lib' pass so they can be used
# to run programs during the `make others' pass.
lib-noranlib: $(objpfx)$(rtld-installed-name) \
              $(addprefix $(objpfx),$(extra-objs))
endif

# Command to link into a larger single relocatable object.
reloc-link = $(LINK.o) -nostdlib -nostartfiles -r

$(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
        $(reloc-link) -o $@ $^

# Link together the dynamic linker into a single relocatable object.
# First we do a link against libc_pic.a just to get a link map,
# and discard the object produced by that link.  From the link map
# we can glean all the libc modules that need to go into the dynamic
# linker.  Then we do a recursive make that goes into all the subdirs
# those modules come from and builds special rtld-foo.os versions that
# are compiled with special flags, and puts these modules into rtld-libc.a
# for us.  Then we do the real link using rtld-libc.a instead of libc_pic.a.

$(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
        @-rm -f $@T
        $(reloc-link) -o $@.o '-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@T
        rm -f $@.o
        mv -f $@T $@

$(objpfx)librtld.mk: $(objpfx)librtld.map Makefile
        LC_ALL=C \
        sed -n 's@^$(common-objpfx)\([^(]*\)(\([^)]*\.os\)) *.*$$@\1 \2@p' \
            $< | \
        while read lib file; do \
          case $$lib in \
          libc_pic.a) \
            LC_ALL=C fgrep -l /$$file \
                  $(common-objpfx)stamp.os $(common-objpfx)*/stamp.os | \
            LC_ALL=C \
            sed 's@^$(common-objpfx)\([^/]*\)/stamp\.os$$@rtld-\1'" +=$$file@"\
            ;; \
          */*.a) \
            echo rtld-$${lib%%/*} += $$file ;; \
          *) echo "Wasn't expecting $$lib($$file)" >&2; exit 1 ;; \
          esac; \
        done > $@T
        echo rtld-subdirs = `LC_ALL=C sed 's/^rtld-\([^ ]*\).*$$/\1/' $@T \
                             | LC_ALL=C sort -u` >> $@T
        mv -f $@T $@

$(objpfx)rtld-libc.a: $(objpfx)librtld.mk FORCE
        $(MAKE) -f $< -f rtld-Rules

$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(objpfx)rtld-libc.a
        $(LINK.o) -nostdlib -nostartfiles -r -o $@ '-Wl,-(' $^ -lgcc '-Wl,-)' \
                  -Wl,-Map,$@.map

generated += librtld.map librtld.mk rtld-libc.a librtld.os.map

z-now-yes = -Wl,-z,now

$(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
        @rm -f $@.lds
        $(LINK.o) -nostdlib -nostartfiles -shared $(z-now-$(bind-now))  \
                  $(LDFLAGS-rtld) -Wl,-z,defs -Wl,--verbose 2>&1 |      \
                  LC_ALL=C \
                  sed -e '/^=========/,/^=========/!d;/^=========/d'    \
                      -e 's/\. = .* + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' \
                  > $@.lds
        $(LINK.o) -nostdlib -nostartfiles -shared -o $@                 \
                  $(LDFLAGS-rtld) -Wl,-z,defs $(z-now-$(bind-now))      \
                  $(filter-out $(map-file),$^) $(load-map-file)         \
                  -Wl,-soname=$(rtld-installed-name) -T $@.lds
        rm -f $@.lds
        readelf -s $@ \
          | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }'

# interp.c exists just to get this string into the libraries.
CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"' \
                  -DNOT_IN_libc=1
$(objpfx)interp.os: $(common-objpfx)config.make

ifneq (ld.so,$(rtld-installed-name))
# Make sure ld.so.1 exists in the build directory so we can link
# against it.
$(objpfx)$(rtld-installed-name): $(objpfx)ld.so
        rm -f $@
        ln -s $(<F) $@
generated += $(rtld-installed-name)
endif

# Build a file mentioning all trustworthy directories to look for shared
# libraries when using LD_LIBRARY_PATH in a setuid program.  The user can
# add directories to the list by defining $(user-defined-trusted-dirs)
# before starting make.
$(objpfx)trusted-dirs.h: $(objpfx)trusted-dirs.st; @:
$(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig
        $(make-target-directory)
        echo "$(subst :, ,$(default-rpath) $(user-defined-trusted-dirs))"    \
        | $(AWK) -f gen-trusted-dirs.awk > ${@:st=T};
        echo '#define DL_DST_LIB "$(notdir $(slibdir))"' >> ${@:st=T}
        $(move-if-change) ${@:st=T} ${@:st=h}
        touch $@
CPPFLAGS-dl-load.c = -I$(objpfx). -I$(csu-objpfx).

ifeq (yes,$(build-shared))
$(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force)
        $(make-target-directory)
        $(do-install-program)

$(inst_slibdir)/$(rtld-installed-name): \
  $(inst_slibdir)/$(rtld-version-installed-name) \
  $(inst_slibdir)/libc-$(version).so
        $(make-shlib-link)

# Special target called by parent to install just the dynamic linker.
.PHONY: ldso_install
ldso_install: $(inst_slibdir)/$(rtld-installed-name)
endif


common-ldd-rewrite = -e 's%@RTLD@%$(slibdir)/$(rtld-installed-name)%g' \
                     -e 's%@VERSION@%$(version)%g' \
                     -e 's%@PKGVERSION@%$(PKGVERSION)%g' \
                     -e 's%@REPORT_BUGS_TO@%$(REPORT_BUGS_TO)%g'
sh-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%/bin/sh%g;s/\$$"/"/g'
bash-ldd-rewrite = $(common-ldd-rewrite) -e 's%@BASH@%$(BASH)%g' \
                   -e 's%@TEXTDOMAINDIR@%$(msgcatdir)%g'



参考文献