동적 라이브러리의 실제 동작 방법에 대해...(elf)

kkojiband의 이미지

이 글은 동적 라이브러리가 실제로 어떤 식으로 동작을 하는지에 관한 글입니다. elf 에 대해 자세히 공부해보지 못하신 분들(저도)은 한번 읽어보시면 도움이 될듯(?)합니다. 별 쓸모는 없겠지만요...-_-;
그리고 설명이 더 필요한 부분이나 잘못된 내용이 있다면 고수님들께서 가차없이 지적해주시기 바랍니다~!

먼저, 실행 프로그램에서 동적 라이브러리가 어떤 식으로 동작을 하는지에 대해 알아보도록 하겠습니다.( 각 section 들에 대한 설명은 생략하도록 하겠습니다 )

다 아시다시피 프로그램이 실행이 되려면 참고하고 있는 모든 심볼들이 실제 위치한 주소로 해석이 되어 있어야 합니다. 하지만 동적으로 링킹되는 라이브러리는 실제로 로딩이 되기 전까지는 메모리의 어느 위치로 올라올지 알수가 없습니다. (여기서 말하는 위치는 물리 주소가 아니고 논리 주소입니다. 물리 주소야 어차피 페이징을 통해 아무곳이나 상관이 없으니까요...)
하지만 실행 가능한 코드를 어셈 코드로 덤프해보신 분들은 아시겠지만 동적 링킹되어야하는 심볼들도 특정 주소로 해석이 되어 있습니다. 대체 이 주소는 무엇일까요?

1.

 section .text:
0848328 <main>:
 ...
 8048340:	e8 23 ff ff ff 	call 8048268 <...>
 ...

동적 링킹시킨 printf 를 호출하는 부분입니다.

2.

 section .plt:
08048248 <.plt>:
 ...
 8048268:	ff 25 00 95 04 08  	jmp *0x8049500 <...>
 ...

우리가 printf 를 호출한 곳에서 실제로 호출한 부분입니다.

3.

 section .got:
08494f0 <_GLOBAL_OFFSET_TABLE_>:
 ...
 8049500:	6e 82 04 08	...
 ...

처음에 1 번에서 2 번을 호출을 합니다. 이렇게 되면 스택에 그 다음 주소가 저장이 되고 2 번에서는 0x8049500 번 주소가 가리키고 있는 주소로 점프를 하게 됩니다. 여기서 현재 스택에 저장되어있는 값은 1번에서 저장한 값이기 때문에 실제로 함수를 끝마친 뒤에는 1번의 다음 명령어로 복귀하게 됩니다. 그리고 가만히 보면 0x8049500 의 주소에 어떤 값이 저장이 되어있죠? 이 값은 동적 링크 로더에 의해 실제 참조해야할 주소로 교체가 됩니다. 그렇다고 위에 있는 0x804826e 라는 값이 전혀 무의미한 값은 아닙니다. 더 자세한 내용은 직접 덤프해서 한번 분석해보시기 바랍니다.

여기까지 이해를 하셨다면 실행 프로그램에서 어떤 식으로 동적 링킹된 심볼들을 참조하는지에 대해서는 조금이나마 알게 되셨을겁니다. 하지만 여기서 또 하나의 의문점이 생깁니다.
동적 라이브러리는 말그대로 메모리에는 단 한번 올라와있고, 여기저기 필요한 프로그램들이 가져다가 쓰는 것을 말합니다. 리눅스에서는 각 프로세스마다 독립적인 4Gb 의 선형 주소공간을 가지고 있어서 각 프로세스가 사용하는 주소는 전혀 별개의 주소가 되는데 어떻게 하나의 동적 라이브러리 코드가 이 모든 프로세스 상에서 제대로 실행이 될수있을까요?

이제 이것에 대해 설명을 해드리겠습니다...

동적 라이브러리를 컴파일할때 특별한 옵션을 줍니다. 그래서 정적 라이브러리와는 약간 다른 코드가 생성이 됩니다. 이걸 두고 동적 라이브러리를 위치 독립적인 코드라고 합니다. 실제로 어떤 식으로 동작하는지를 살펴보면,

 section .text:
00000700 <bbb>:
 ...
 707:	38 00 00 00 00	call	70c <...>
 70c:	5b		           pop	%ebx
 70d:	81 c3 90 11 00 00	add	$0x1190, %ebx
 ...

먼저, call 70c 를 하면 다음 명령어(70c)가 실제 메모리 상에 올라와있는 주소가 스택에 저장이 되고 70c 로 이동을 합니다. 70c 에서 pop %ebx 는 현재 스택에 있는 내용을 가져옵니다. 이렇게 되면 어떻게 될까요? 바로 70c 에 해당하는 명령어가 실제 메모리에 위치한 곳의 주소가 ebx 에 저장이 됩니다. 그리고 그 다음 명령어를 보시면, 이 ebx 에 0x1190 을 더합니다. 그 결과 값은 다름이 아니라 .got section 의 베이스 어드레스가 됩니다...
여기서부터는 위에서 실행 프로그램이 동적 링킹된 심볼들을 해석하는 부분과 비슷한 알고리즘을 사용을 합니다. 단, 실행 프로그램에서는 .got section 의 베이스 어드레스가 링킹시에 이미 고정이 되어 있기 때문에 위에서 설명한 것과 같이 .text 와 .plt section 에서는 고정된 주소들을 지정을 해줄수가 있었습니다. 하지만 어느 프로세스에서 어느 주소로 링킹이 될지 모르는 동적 라이브러리는 방금 설명드린 방법으로 .got section 의 베이스 어드레스를 구해서 심볼들을 해석을 해서 사용하게 됩니다.
추가적으로 이렇게 구한 .got section 의 베이스 어드레스는 정적으로 선언된 심볼들의 오프셋 위치를 계산하기 위한 기준점으로도 사용됩니다...
이런 식으로해서 프로세스가 동적 라이브러리를 자신의 선형 주소 공간 어디에 링킹을 시켜놓아도 그것이 실행가능하게 되는겁니다...

간단하죠? ^^; 제가 글재주가 없어서 설명을 잘못합니다. 작은 내용이지만 조금이나마 도움이 되었으면 합니다. 그럼 이만...!

Forums: 

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.