프로그램 컴파일 과정



변수 종류별 주소 공간

maptest1.c

  • gcc의 경우 컴파일시 초기화되지 않은 지역변수는 0으로 초기화 한다.(stack-boundary=32비트 기준)
  • 결과

    1. global_num_1(초기화하지않은 전역 변수)
      • .bss
      • 0x0804A02C에 00 00 00 00로 저장됨
    2. global_num_2(초기화한 전역 변수)
      • .data
      • 0x0804A018에 64 00 00 00으로 저장
    3. local_num_1(초기화하지 않은 지역 변수)
      • stack
      • 0xBFFFF384에 00 00 00 00으로 저장
    4. local_num_2(초기화한 지역변수)
      • stack
      • 0xBFFFF380에 C8 00 00 00으로 저장
      • stack은 높은 주소에서 낮은 주소 방향으로 할당되므로, 변수가 생성될 때 스택의 위쪽(낮은 주소)에 위치한다. (local_num_2의 주소 < local_num_1의 주소)
    5. static_num_1(초기화하지않은 static 지역 변수)
      • .bss
      • 0x0804A028에 00 00 00 00으로 저장
    6. static_num_2(초기화한 static 지역 변수)
      • .data
      • 0x0804A01C에 00 00 00 00으로 저장
  • 문자는 1바이트 크기의 정수값(ASCII 코드)으로 저장되므로, char charA = 'a';의 경우 메모리에 0x61이 저장된다.
  • maptest1.c의 .rodata에는 14 ~ 30의 문자열 상수들이 있다.

배열 주소 공간

maptest2.c

  • 결과

    1. global_char_arr_1(초기화하지않은 배열 전역변수)
      • .bss
      • &arr arr &arr[0]
    2. global_char_arr_2(초기화한 배열 전역변수)
      • .data
    3. local_char_arr_1(초기화하지않은 배열 지역 변수)
      • stack
    4. local_char_arr_2(초기화한 배열 지역 변수)
      • stack
  • char 배열, int g3[5] = {'a', 'b', 'c', 'd', 'e'};의 경우 각 원소는 4바이트 정수로 변환되어 메모리에 0x61 00 00 00, 0x62 00 00 00, 0x63 00 00 00, 0x64 00 00 00, 0x65 00 00 00 형태로 저장된다.
  • 정수 배열 int l3[5] = {1, 2, 3, 4, 5};의 경우도 각 정수는 4바이트 크기로 변환되어 0x01 00 00 00, 0x02 00 00 00, 0x03 00 00 00, 0x04 00 00 00, 0x05 00 00 00 형태로 저장된다.
  • 문자열 주소 공간 확인 (.rodata)

    • “My”, “World” → .data 영역 (직접 초기화 → 변수 따라감)
    • 나머지 문자열 상수들 → .rodata
  • 배열 전역 변수

    1. golobal_char_arr_1(초기화하지않은 배열 전역 변수)
      • .bss에 위치(0x0804A028)
    2. .rodata에 있는 문자열 상수 “Hi” copy
      • .global_char_arr_1(0x0804A028)에 “Hi” 복사
    3. global_char_arr_2(초기화한 배열 전역 변수)
      • data영역에 위치(0x0804A028)
      • .text에서 읽은 문자열을 .rodata가 아닌 .data에 바로 초기화
  • 배열 로컬 변수

    1. local_char_arr_1 (초기화하지않은 배열 지역 변수)
      • stack(0xBFFFF37E)에 위치
    2. .rodata에 있는 문자열 상수 “Array” Copy
      • .rodata에 있는 문자열 상수 copy
    3. local_char_arr_2(초기화한 배열 지역 변수)
      • stack(0xBFFFF377)에 위치
      • .text에서 읽은 “World!”를 stack에 바로 초기화
      • Little Endian
        • 하위 바이트의 값을 작은 번지수에 저장
        • 데이터를 저장할 때 역순으로 저장
        • 주로 CISC 계열 : Intel, 80x86, AMD

포인터 주소 공간

maptest3.c

  • 초기화 하지 않은 포인터 전역 변수

    1. global_char_ptr_1(초기화 하지 않은 포인터 전역 변수)
      • .bss(0x0804A02C)에 위치
      • global_char_ptr_1의 값은 NULL로 초기화 된다.(00 00 00 00)
    2. heap에 3만큼의 메모리 영역 생성(0x0804B008)
      • 0x0804A02C에 할당한 메모리 주소(0x0804B008)를 리틀 엔디안으로 넣음
    3. .rodata에 있는 “Hi”를 global_char_ptr_1(0x0804B008)에 복사함
  • 초기화한 포인터 전역 변수

    1. “My”는 .rodata(0x080486C0)에 위치
    2. global_char_ptr_2(초기화한 포인터 전역 변수)
      • .data(0x0804A020)에 위치
      • “My”의 위치(0x080486C0)를 C0 86 04 08(리틀 엔디안)로 저장
  • 포인터 로컬변수

    1. local_char_ptr_1(초기화하지 않은 지역 변수)
      • stack(0xBFFFF384)에 위치
    2. heap에 8 크기의 공간 할당(0x0804B018)
    3. .rodata에 있는 “Pointer”를 할당한 공간(0x0804B018)에 Copy
    4. local_char_ptr_2(초기화한 지역 변수)
      • stack(0xBFFFF380)에 위치
    5. .rodata에 있는 “World!”의 주소(0x08486C3)을 local_char_ptr_2(0xBFFFF380)에 리틀 엔디안으로 저장

출처

  • 숭실대학교 이정현 교수님 시스템 보안