Linking 2(11)

G·2022년 11월 13일
0

2-2 System programming

목록 보기
9/15

Linking

이전 포스트에서 정적 링킹을 정리하였다. 이번엔 동적링킹을 알아보자.

만약 개발자가 자신의 프로그램에 새로운 라이브러리를 추가하려면 어떻게 해야할까?

  • 라이브러를 하나의 소스파일에 넣어 자신의 프로그램과 링킹한다.
    이 방법은 편하지만 공간과 시간 효율이 떨어진다.
  • 각각의 함수들을 분할된 소스파일에 저장한다.
    명시적으로 이진파일을 그들의 프로그램에 link해야한다.
    위의 경우보다 효율적이지만 프로그래머가 힘들어진다. 그런데 이진파일을 link 하는게 뭘까?

Static libraries(.a archive)

Relocatable 오브젝트 파일들을 보관하는 하나의 파일이다. linux에서 아카이브라 불리운다.

첫 번째 명령어는 오브젝트들의 집합을 볼 수 있다.
두 번째 명령어는 아카이브의 목록을 볼 수 있다.

C 주요 아카이브

  • libc.a는 C standard library이다. I/O, memory allocation 등의 함수들을 저장한 아카이브 파일이다.
  • libm.a는 C math library이다.


위의 내용에서 addvec.c와 multvec.c를 오브젝트 파일로 링킹 이전으로 만들어준다. -c 옵션
이후 ar -rs 부분을 보면 오브젝트 파일을 하나의 아카이브로 묶어주는 명령어를 사용한다. -r 옵션은 오브젝트 파일을 하나의 아카이브에 추가하고 이미 존재한다면 치환한다. -s 옵션은 아카이브 인덱스를 생성한다. 그냥 넘어가자. 속도에 대한 옵션이다.
그리고 -static으로 정적링킹을하여 main.c와 링킹해주는 것을 확인할 수 있다.

위의 부분은 정적링킹의 과정이다. 아카이브에 넣어 링킹한다.
그렇다면 a.out 실행 파일이 생성된다.

Using Static Libraries

정적 링킹을 할 경우 새로운 오브젝트 파일의 external reference에 resolving을 거쳐야 한다. definition과 연결해줘야 하기에 만약 이게 하나라도 되지 않았다면 entry(unresolved reference)가 list에 남아있다면.(링커는 정적 링킹되는 오브젝트 파일을 resolution할 때 list의 형태에 저장하여 진행한다.)

두 번째 줄 정적링킹 옵션에서 아카이브가 뒤에 올 때 resolved가 일어나지 못해 에러를 내는 모습이다.
정적 링킹의 추가 문제점은 아래와 같다

  • 저장된 실행파일에 중복이 생긴다질문
  • 작은 버그를 고치기 위해서 계속해서 링킹을 해야한다.

Solution: Shared Libraries

위의 문제를 해결하기 위해 공유 라이브러리를 사용하면 된다.
코드와 데이터를 가지고 있는 오브젝트 파일을 동적으로 링킹하는 것이다. run time이나 load time에 linking한다.
특정 라이브러리의 하나의 copy를 공유한다.
하나의 copy의 .text section는 메모리에 load된 이후 어떠한 프로세스가 사용할 수 있다.
처음으로 함수가 호출될 때 런타임 때 업데이트하기에 작지 않은 오버헤드가 있다.

Load time

Load-time 동적 링킹은 실행파일이 메모리에 로드될 때 일어난다.(linux의 동적 링커에 의해 행해진다.)
Standard C Library는 대개 동적으로 링킹된다.

동적 링킹은 프로그램이 load된 이후 runtime 때 발생하기도 한다. 이를 run time linking이라 부른다.
linux에서 dlopen() 함수로 run time linking을 할 수 있다.

소프트웨어를 버전업(정적링킹) 하는 것이 아니라,
소프트웨어가 실행 중(동적링킹)인 상황에 함수만 새로 추가할 수 있다.

-shared 옵션은 링커에게 새로운 공유 오브젝트 파일을 만들게 한다.
-fpic 옵션은 컴파일러에게 position-independent 코드를 생성하게 한다.


위의 코드를 보면 dlopen은 동적 라이브러리의 파일의 handle을 가져온다. 이는 파일의 주소를 뜻한다. 그리고 dlsym 함수를 사용하여 사용할 함수나 변수명을 받아온다. 함수포인터로 받아와 함수를 호출하는 것을 확인할 수 있다.
RTLD_LAZY는 함수가 호출될 때 동적 라이브러리를 .so를 메모리에 loading 한다.

Interpositioning

Library Interpositioning은 라이브러를 끼어넣는 것이다 이게 뭘까?
링킹을 이용하여 개발자가 함수의 호출을 중간에 가로챌 수 있는 기술을 의미한다.
이는 Compile time, Link time, Load/Run time에 일어난다. Link time은 정적링킹을 뜻한다.
Library Interpositioning의 응용은 아래와 같다

  • 함수의 호출을 count할 수 있다.
  • 함수의 호출부와 매개변수에 특성을 부여할 수 있다.(위치와 매개변수를 바꿀 수 있음)
  • Malloc tracing: 메모리 누수를 감지할 수 있다. 주소를 추적할 수 있다.

malloc() 함수를 통해 세 가지 Library Interpositioning을 알아보자.
이 예시의 목표는 할당된 주소와 크기를 추적하고 메모리 할당을 해제한다. 기존의 소스코드를 수정하지 않고 라이브러리만 추가하여 진행한다.







profile
열심히 안 사는 사람

0개의 댓글