ELF Relocations (AArch64)
ELF 규격의 실행 파일 또는 링커블 오브젝트 파일에서 수행하는 리로케이션 작업을 알아본다.
- 컴파일 타임
- static 선언된 함수들과 변수들은 컴파일 타임에 주소가 결정되므로 이들 주소에 대해 리로케이션 엔트리를 생성하지 않는다.
- static 선언하지 않은 함수들과 변수들은 컴파일 타임에 주소를 결정하지 않아 리로케이션 엔트리를 .rela 섹션에 만들어 둔다.
- 링크 타임
- 스태틱 링킹 vs 다이나믹 링킹
- 오브젝트 파일 및 외부 라이브러를 포함하여 스태틱 링킹을 수행할 때 재배치(relocations) 작업을 링커가 할 수가 있다.
- 사용자의 요청에 따라 일부분은 로딩 타임에 다이나믹 링킹을 수행할 때 재배치(relocations) 작업을 하도록 결정할 수 있다.
- 다이나믹 링킹을 할 외부 공유 라이브러리 심볼들에 대해서는 리로케이션 엔트리를 .rela 섹션에 만들어 둔다.
- .got 섹션에 점프할 주소 영역을 만들어두고, .plt 섹션에 .got 테이블의 대응하는 해당 주소값을 알아와서 branch하는 코드를 생성한다.
- 스태틱 링킹 vs 다이나믹 링킹
- 로딩 타임(다이나믹 링킹)
- 외부 공유 라이브러리를 다이나믹 링크한 경우 호출할 주소가 결정되지 않았다. 이들을 위해 .rela 섹션에 만들어진 리로케이션 엔트리를 대상으로 호출할 공유 라이브러리의 각 함수 주소들을 결정하여 메모리에서 갱신한다.
- got 섹션의 got 테이블에 사용할 공유 라이브러리의 심볼 주소가 갱신된다.
.rela 섹션
리로케이션 엔트리들은 .rela 섹션에 위치한다.
다음 그림은 링크 타임과 로드 타임에 .rela.* 섹션에 위치한 리로케이션 엔트리를 사용하여 주소 갱신을 수행하는 모습을 보여준다.
리로케이션 엔트리 구조
ELF32 규격의 경우 12 바이트 엔트리를 사용한다.
glibc/elf/elf.h – ELF32
typedef struct { Elf32_Addr r_offset; uint32_t r_info; int32_t r_addend; } Elf32_Rela;
- r_offset
- 리로케이션할 offset 주소를 담는다.
- r_info
- 상위 3 바이트에 심볼 인덱스와 하위 1 바이트에 리로케이션 타입을 담는다.
- 심볼 인덱스가 0인 경우 null 인덱스라고 한다.
- r_addend
- 리로케이션 타입에 따라 수행시 추가되어야 할 값을 담는다.
32비트 ELF 파일의 경우 4 바이트의 info 필드에서 상위 3 바이트를 심볼 인덱스가 사용하고, 나머지 하위 1 바이트를 타입으로 사용한다.
ELF64 규격의 경우 24 바이트 엔트리를 사용한다.
glibc/elf/elf.h – ELF64
typedef struct { Elf64_Addr r_offset; uint64_t r_info; int64_t r_addend; } Elf64_Rela;
- r_offset
- 리로케이션할 offset 주소를 담는다.
- r_info
- 상위 4 바이트에 심볼 인덱스와 하위 4 바이트에 리로케이션 타입을 담는다.
- 심볼 인덱스가 0인 경우 null 인덱스라고 한다.
- r_addend
- 리로케이션 타입에 따라 수행시 추가되어야 할 값을 담는다.
64비트 ELF 파일의 경우 8 바이트의 info 필드에서 상위 4 바이트를 심볼 인덱스가 사용하고, 나머지 하위 4 바이트를 타입으로 사용한다.
C 언어 데이타 타입 모델
GCC 및 Linux는 C 언어 데이터 타입 모델에서 64 비트 시스템은 LP64 모델을 사용하고, 32 비트 시스템은 ILP32를 사용한다.
리로케이션 기호 표기법
리로케이션 동작에 대한 기호 표시는 다음과 같다.
- S
- 심볼 주소
- A
- Addend 값
- P
- 리로케이트될 장소의 주소
- X
- 리로케이션 동작의 결과
- Page(expr)
- 페이지 단위의 주소로 하위 12비트가 0으로 클리어된다.
- GOT
- Global Offset Table로 다이나믹 링크(로드) 타임에 갱신된다.
- GDAT(S+A)
- GOT 내 64비트 엔트리가 S+A 로 동작한다.
- G(expr)
- GOT 내 64비트 엔트리 주소
- Delta(S)
- 스태틱 링크 타임에 결정된 프로그램 시작 주소와 실행 타임에 변경된 프로그램 시작 주소의 차이(Delta)를 기존 심볼 주소에 더해 반영한다.
- S + delta
- 스태틱 링크 타임에 결정된 프로그램 시작 주소와 실행 타임에 변경된 프로그램 시작 주소의 차이(Delta)를 기존 심볼 주소에 더해 반영한다.
- _NC
- None Checking 리로케이션 타입으로 오버플로우 체크를 수행하지 않는다.
리로케이션 타입
ELF format for AArch64에서 사용하는 리로케이션 엔트리 타입들 다음과 같이 많은 종류가 있다.
glibc/elf/elf.h
/* ILP32 AArch64 relocs. */ #define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */ #define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */ #define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */ #define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */ #define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */ #define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */ #define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */ #define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */ #define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */ #define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */
/* LP64 AArch64 relocs. */ /* 1. Static Data relocs. */ #define R_AARCH64_ABS64 257 /* Direct 64 bit. */ #define R_AARCH64_ABS32 258 /* Direct 32 bit. */ #define R_AARCH64_ABS16 259 /* Direct 16-bit. */ #define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */ #define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */ #define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */ #define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */햬
GOT-relative 데이터 리로케이션 타입들이다.
- R_AARCH64_ABS64
- 데이터 리로케이션 타입으로 S + A와 같이 동작한다.
- R_AARCH64_ABS32
- 데이터 리로케이션 타입으로 S + A와 같이 동작한다. 단 2^32 범위 내에서 사용되어야 한다.
- R_AARCH64_PREL32
- 데이터 리로케이션 타입으로 S + A – P와 같이 동작한다. 단 2^32 범위 내에서 사용되어야 한다.
/* 2. Static AArch64 relocs. */ /* 1) Group relocations to create a 16-, 32-, 48-, or 64-bit unsigned data value or address inline */ #define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */ #define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */ #define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */
/* 2) Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline */ #define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */ #define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */ #define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */
/* 3) Relocations to generate 19, 21 and 33 bit PC-relative addresses */ #define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */ #define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */ #define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */ #define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */ #define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */ #define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */
- R_AARCH64_ADR_PREL_PG_HI21
- Page(S + A) – Page(P)
- ADRP 명령을 사용하여 4K 페이지 단위의 PC 기반 relative offset 주소(범위는 +-4GB)를 참조한다. 이 값을 4K로 나누어 hi21 필드에 사용한다.
- 예) adrp x0, var1
- C 예) value = *ptr; object 파일 내부의 포인터 변수 참조
- R_AARCH64_ADD_ABS_LO12_NC
- S + A
- ADD 명령을 사용하여 PC 기반 relative offset 주소의 하위 12비트 절대 주소를 참조한다. 이 값은 lo12 필드에 사용한다.
- 예) add x0, var1
- C 예) value = *ptr; object 파일 내부의 포인터 변수 참조
/* 4) Relocations for control-flow instructions - all offsets are a multiple of 4 */ #define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */ #define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */ #define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */ #define R_AARCH64_CALL26 283 /* Likewise for CALL. */
- R_AARCH64_JUMP26
- S + A – P
- PC + relative offset 주소(범위는 +-128MB)를 참조한다. 이 값을 4로 나누어 imm26 필드에 사용한다.
- S + A – P
- R_AARCH64_CALL26
- PC + relative offset 주소(범위는 +-128MB)를 참조한다. 이 값을 4로 나누어 imm26 필드에 사용한다.
- 예) bl sub1 <- .globl 선언 함수
- C 예) sub1(); <- static 선언하지 않은 함수
- PC + relative offset 주소(범위는 +-128MB)를 참조한다. 이 값을 4로 나누어 imm26 필드에 사용한다.
/* 3)에 포함 */
#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */
#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */
#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */
- R_AARCH64_LDST64_ABS_LO12_NC
- S + A
- 주소를 LD/ST 명령의 상수 값을 imm9 필드에 사용한다.
/* 5) Group relocations to create a 16, 32, 48, or 64 bit PC-relative offset inline */ #define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */ #define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */ #define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */ #define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */ #define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */
/* 6) Group relocations to create a 16, 32, 48, or 64 bit GOT-relative offsets inline */ #define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */ #define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */ #define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */ #define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */ #define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */
/* 7) GOT-relative data relocations */ #define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */ #define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */
/* 8) GOT-relative instruction relocations */ #define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */ #define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */ #define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */ #define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */ #define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */
- R_AARCH64_ADR_GOT_PAGE
- Page(G(GDAT(S + A))) – Page(P)
- 오브젝트 파일 외부 주소를 참조하기 위해 GOT 엔트리에 대해 R_AARCH64_ADR_PREL_PG_HI21 타입과 동일하게 동작한다.
- 예0 adrp x0, var2 (extern)
- C 예) value = *ptr; (extern)
- R_AARCH64_LD64_GOT_LO12_NC
- G(GDAT(S + A))
- 오브젝트 파일 외부 주소를 참조하기 위해 GOT 엔트리에 대해 R_AARCH64_ADD_ABS_LO12_NC타입과 동일하게 동작한다.
- 예) add x0, var1 (extern)
- C 예) value = *ptr; (extern)
/* 3. Relocations for thread-local storage */ /* 1) General Dynamic TLS relocations */ #define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */ #define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */ #define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */ #define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */ #define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */
/* 2) Local Dynamic TLS relocations */ #define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */ #define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */ #define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */ #define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */ #define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */ #define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */ #define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */ #define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */ #define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */ #define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */ #define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */ #define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */ #define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */ #define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */ #define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */ #define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */ #define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */ #define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */ #define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */ #define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */ #define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */ #define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */
/* 3) Initial Exec TLS relocations */ #define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */ #define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */ #define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */ #define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */ #define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */
/* 4) Local Exec TLS relocations */ #define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */ #define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */ #define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */ #define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */ #define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */ #define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */ #define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */ #define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */ #define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */ #define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */ #define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */ #define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */ #define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */ #define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */ #define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */ #define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */
/* 5) TLS descriptor relocations */ #define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */ #define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */ #define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */ #define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */ #define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */ #define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */ #define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */ #define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */ #define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */ #define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */
/* 2)에 포함 */ #define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */ #define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */
/* 4)에 포함 */ #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */ #define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */
/* 4. Dynamic relocs. */ #define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */ #define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */ #define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */ #define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ #define R_AARCH64_TLS_DTPMOD 1028 /* Module number, 64 bit. */ #define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset, 64 bit. */ #define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset, 64 bit. */ #define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ #define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
런타임에 다이나믹 리로케이션시 사용되는 리로케이션 타입들이다.
- R_AARCH64_GLOB_DAT
- GOT 엔트리를 생성한다.
- S + A
- R_AARCH64_JUMP_SLOT
- PLT 엔트리를 생성한다.
- S + A
- R_AARCH64_RELATIVE
- 스태틱 링크 타임에 결정한 주소와 다이나믹 링크 타임에 결정한 주소가 달라지면 그 차이만큼을 더해서 갱신해야 하는 경우 사용된다.
- 프로그램 로딩 후 시작 주소가 달라지면 변경되어야 하는 항목에 사용된다.
- Delta(S) + A
- = S + Delta + A
- 리눅스 커널 이미지
- 보안을 위해 리눅스 커널 이미지가 매핑되는 가상 주소가 랜덤하게 달라질 수 있다. 이러한 경우 커널에서 외부로 export 된 심볼들의 주소들도 바뀌어야 한다. 이들을 지원하기 위해 커널 역시 특별한 리로케이션 엔트리가 준비되어 있다. 이들 타입에 해당하는 모든 주소들을 바뀐 가상 주소 offset을 더해 변경한다.
PLT(Program Linkage Table)
PLT 엔트리는 실행 파일의 바깥쪽 멀리 있는 목적지 주소로 브랜치(long-branch)하기 위한 코드가 구현된다.
- 일반적으로 목적지의 이름은 알고 있지만, 주소는 모르는 경우 이를 imported symbol이라고 불리운다.
- PLT 엔트리는 일반적으로 GOT 엔트리로 부터 목적지 주소를 읽어오도록 구현한다.
GOT(Global Object Table)
GOT 엔트리는 다이나믹 링크 타임에 갱신되는 8 바이트 주소가 담긴다.
- SysV-based Dynamic Shared Objects (DSOs), 즉 공유 라이브러리 함수들에 대한 접근은 프로그램이 로딩되어 다이나믹 링크 타임에 목적지 주소를 알 수 있게된다.
PLT(Program Linkage Table) 및 GOT(Global Object Table) 연동
실행 파일이 로딩되어 다이나믹 링크가 수행될 때 사용할 공유 라이브러리의 심볼 주소를 .got 섹션의 got 테이블에 갱신한다. 이 주소는 실행 코드 -> PLT 엔트리 코드가 -> GOT 엔트리에 있는 주소를 통해 long-branch 할 수 있게 한다.
- .text 섹션에 위치한 printf() 호출 코드는 bl <label> 형태의 어셈블리 코드를 통해 +-128M 범위내에 위치한 .plt 섹션에 생성된 코드를 호출한다.
- .plt 섹션에 위치한 코드는 .got 섹션에 있는 8 바이트 주소를 읽어와서 br <Xd> 형태의 어셈블리 코드를 통해 범위 제한 없이 호출할 수 있다.
- .got 섹션에 위치한 8 바이트 주소는 실행 파일을 로딩하고 다이나믹 링크가 수행될 때 사용할 공유 라이브러리의 심볼 주소로 갱신된다.
Relocatable vs PIC(Position Independent Code)
- Relocatable
- 링킹 타임에 스태틱 링킹에 의해 실행 주소 및 각 심볼들에 대한 주소가 결정되어 재배치한다.
- 로딩 타임에 다이나믹 링킹에 실행 주소의 변경 또는 사용하는 외부 공유 라이브러리의 심볼 주소들에 주소가 결정되어 재배치한다.
- PIC
- 링커에 의해 실행된 주소가 의미가 없어 어느 공간에든 위치할 수 있도록 코드를 구성하게 한다.
- 공유 라이브러리를 빌드하는 경우에도 일반적으로 -fPIC 옵션을 사용하여야 한다.
샘플 C 소스
main.c에서 몇 개의 주소를 참조한다.
- 내부의 var1 변수 주소를 참조한다.
- 외부 파일 sub.c에 존재하는 함수 sub1()과 변수 var2 주소를 참조한다.
- 외부 공유 라이브러리에 있는 출력 함수 printf() 주소를 참조한다.
main.c
#include <stdio.h> extern int sub1(); extern int var2; int var1 = 10; void main() { sub1(); printf("hello. var1=%d, var2=%d\n", var1, var2); }
sub.c 파일에서는 아무 조소도 참조하지 않게 하였다.
sub.c
int var2 = 20; int sub1() { return 1; }
main.c 파일을 컴파일한 후 main.o 파일의 섹션을 알아본다.
- 코드 내에서 주소들을 참조하므로 .rela.text 섹션이 생성된 것을 확인할 수 있다.
$ gcc -c main.c $ readelf -S main.o There are 11 section headers, starting at offset 0x398: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 000000000000003c 0000000000000000 AX 0 0 4 [ 2] .rela.text RELA 0000000000000000 00000280 00000000000000c0 0000000000000018 I 8 1 8 [ 3] .data PROGBITS 0000000000000000 0000007c 0000000000000004 0000000000000000 WA 0 0 4 [ 4] .bss NOBITS 0000000000000000 00000080 0000000000000000 0000000000000000 WA 0 0 1 [ 5] .rodata PROGBITS 0000000000000000 00000080 0000000000000019 0000000000000000 A 0 0 8 [ 6] .comment PROGBITS 0000000000000000 00000099 0000000000000031 0000000000000001 MS 0 0 1 [ 7] .note.GNU-stack PROGBITS 0000000000000000 000000ca 0000000000000000 0000000000000000 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 000000d0 0000000000000180 0000000000000018 9 11 8 [ 9] .strtab STRTAB 0000000000000000 00000250 0000000000000029 0000000000000000 0 0 1 [10] .shstrtab STRTAB 0000000000000000 00000340 0000000000000052 0000000000000000 0 0 1
sub.c 파일을 컴파일한 후 sub.o 파일의 섹션을 알아본다.
- 코드 내에서 하나의 주소 참조도 없어 .rela.text 섹션이 생성되지 않은 것을 확인할 수 있다.
$ gcc -c main.c $ readelf -S sub.o There are 9 section headers, starting at offset 0x1e8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000008 0000000000000000 AX 0 0 4 [ 2] .data PROGBITS 0000000000000000 00000048 0000000000000004 0000000000000000 WA 0 0 4 [ 3] .bss NOBITS 0000000000000000 0000004c 0000000000000000 0000000000000000 WA 0 0 1 [ 4] .comment PROGBITS 0000000000000000 0000004c 0000000000000031 0000000000000001 MS 0 0 1 [ 5] .note.GNU-stack PROGBITS 0000000000000000 0000007d 0000000000000000 0000000000000000 0 0 1 [ 6] .symtab SYMTAB 0000000000000000 00000080 0000000000000108 0000000000000018 7 9 8 [ 7] .strtab STRTAB 0000000000000000 00000188 0000000000000017 0000000000000000 0 0 1 [ 8] .shstrtab STRTAB 0000000000000000 0000019f 0000000000000045 0000000000000000 0 0 1
test 실행 파일의 섹션을 알아본다.
- .rela.dyn 및 .rela.plt 섹션이 생성되었음을 확인한다.
- 또한 새롭게 추가된 .plt 및 .got 섹션을 확인한다.
$ strip test; readelf -S test There are 25 section headers, starting at offset 0x1128: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000000200 00000200 000000000000001b 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 000000000000021c 0000021c 0000000000000020 0000000000000000 A 0 0 4 [ 3] .note.gnu.build-i NOTE 000000000000023c 0000023c 0000000000000024 0000000000000000 A 0 0 4 [ 4] .gnu.hash GNU_HASH 0000000000000260 00000260 000000000000001c 0000000000000000 A 5 0 8 [ 5] .dynsym DYNSYM 0000000000000280 00000280 00000000000000f0 0000000000000018 A 6 3 8 [ 6] .dynstr STRTAB 0000000000000370 00000370 0000000000000089 0000000000000000 A 0 0 1 [ 7] .gnu.version VERSYM 00000000000003fa 000003fa 0000000000000014 0000000000000002 A 5 0 2 [ 8] .gnu.version_r VERNEED 0000000000000410 00000410 0000000000000020 0000000000000000 A 6 1 8 [ 9] .rela.dyn RELA 0000000000000430 00000430 0000000000000108 0000000000000018 A 5 0 8 [10] .rela.plt RELA 0000000000000538 00000538 0000000000000078 0000000000000018 AI 5 20 8 [11] .init PROGBITS 00000000000005b0 000005b0 0000000000000014 0000000000000000 AX 0 0 4 [12] .plt PROGBITS 00000000000005d0 000005d0 0000000000000070 0000000000000010 AX 0 0 16 [13] .text PROGBITS 0000000000000640 00000640 00000000000001cc 0000000000000000 AX 0 0 8 [14] .fini PROGBITS 000000000000080c 0000080c 0000000000000010 0000000000000000 AX 0 0 4 [15] .rodata PROGBITS 0000000000000820 00000820 0000000000000021 0000000000000000 A 0 0 8 [16] .eh_frame PROGBITS 0000000000000844 00000844 0000000000000004 0000000000000000 A 0 0 4 [17] .init_array INIT_ARRAY 0000000000010d78 00000d78 0000000000000008 0000000000000008 WA 0 0 8 [18] .fini_array FINI_ARRAY 0000000000010d80 00000d80 0000000000000008 0000000000000008 WA 0 0 8 [19] .dynamic DYNAMIC 0000000000010d88 00000d88 00000000000001f0 0000000000000010 WA 6 0 8 [20] .got PROGBITS 0000000000010f78 00000f78 0000000000000088 0000000000000008 WA 0 0 8 [21] .data PROGBITS 0000000000011000 00001000 0000000000000018 0000000000000000 WA 0 0 8 [22] .bss NOBITS 0000000000011018 00001018 0000000000000008 0000000000000000 WA 0 0 1 [23] .comment PROGBITS 0000000000000000 00001018 0000000000000030 0000000000000001 MS 0 0 1 [24] .shstrtab STRTAB 0000000000000000 00001048 00000000000000dc 0000000000000000 0 0 1
리로케이션 덤프 분석
main.o 파일에 대한 디스어셈블 코드
아래 주황색 및 파란색 부분은 주소를 참조하는 부분이며 링커를 사용하지 않은 상태이므로 엔코딩된 명령문에서 주소에 관련된 필드가 0인 상태로 아직 완성되지 않았다.
$ objdump -d -D main.o main.o: file format elf64-littleaarch64 Disassembly of section .text: 0000000000000000 <main>: 0: a9bf7bfd stp x29, x30, [sp, #-16]! 4: 910003fd mov x29, sp 8: 94000000 bl 0 <sub1> ; sub1() 호출 c: 90000000 adrp x0, 0 <main> ; va1 값 10: 91000000 add x0, x0, #0x0 14: b9400001 ldr w1, [x0] 18: 90000000 adrp x0, 0 <var2> ; var2 값 1c: f9400000 ldr x0, [x0] 20: b9400002 ldr w2, [x0] 24: 90000000 adrp x0, 0 <main> ; const 문자열 28: 91000000 add x0, x0, #0x0 2c: 94000000 bl 0 <printf> ; printf() 호출 30: d503201f nop 34: a8c17bfd ldp x29, x30, [sp], #16 38: d65f03c0 ret Disassembly of section .data: 0000000000000000 <var1>: 0: 0000000a .word 0x0000000a Disassembly of section .rodata:
main.o 파일의 리로케이션 엔트리
.text 섹션내에서 총 8개의 리로케이션 엔트리가 사용됨을 알 수 있다. 이들은 링크 타임에서 주소 갱신을 위해 활용된다.
- .rodata 영역에는 const 문자열이 포함되어 있다.
$ objdump -r main.o main.o: file format elf64-littleaarch64 RELOCATION RECORDS FOR [.text]: OFFSET TYPE VALUE 0000000000000008 R_AARCH64_CALL26 sub1 000000000000000c R_AARCH64_ADR_PREL_PG_HI21 var1 0000000000000010 R_AARCH64_ADD_ABS_LO12_NC var1 0000000000000018 R_AARCH64_ADR_GOT_PAGE var2 000000000000001c R_AARCH64_LD64_GOT_LO12_NC var2 0000000000000024 R_AARCH64_ADR_PREL_PG_HI21 .rodata 0000000000000028 R_AARCH64_ADD_ABS_LO12_NC .rodata 000000000000002c R_AARCH64_CALL26 printf
test 실행 파일의 리로케이션 엔트리
.rela.dyn 및 .rela.plt 섹션에서 총 16개의 주소 참조가 발생하였다.
- 이 엔트리들은 런타임에 외부 공유 라이브러리 등과 연결될 때 주소 갱신을 위해 사용된다.
$ gcc main.c sub.c; strip test; readelf -r test Relocation section '.rela.dyn' at offset 0x430 contains 11 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000010d78 000000000403 R_AARCH64_RELATIV 740 000000010d80 000000000403 R_AARCH64_RELATIV 6f8 000000010fc0 000000000403 R_AARCH64_RELATIV 808 000000010fd0 000000000403 R_AARCH64_RELATIV 11014 000000010fe8 000000000403 R_AARCH64_RELATIV 788 000000010ff0 000000000403 R_AARCH64_RELATIV 744 000000011008 000000000403 R_AARCH64_RELATIV 11008 000000010fc8 000300000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_deregisterTMClone + 0 000000010fd8 000400000401 R_AARCH64_GLOB_DA 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0 000000010fe0 000600000401 R_AARCH64_GLOB_DA 0000000000000000 __gmon_start__ + 0 000000010ff8 000800000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCloneTa + 0 Relocation section '.rela.plt' at offset 0x538 contains 5 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000010f90 000400000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0 000000010f98 000500000402 R_AARCH64_JUMP_SL 0000000000000000 __libc_start_main@GLIBC_2.17 + 0 000000010fa0 000600000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0 000000010fa8 000700000402 R_AARCH64_JUMP_SL 0000000000000000 abort@GLIBC_2.17 + 0 000000010fb0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 printf@GLIBC_2.17 + 0
main 실행 파일 로드 전의 디스어셈블 코드
아래 파란색상의 글씨는 링크 프로세스를 수행한 후에 갱신된 부분이다.
Disassembly of section .text: 0000000000000744 <main>: 744: a9bf7bfd stp x29, x30, [sp, #-16]! 748: 910003fd mov x29, sp 74c: 9400000d bl 780 <sub1> ; R_AARCH64_CALL26 sub1 750: b0000080 adrp x0, 11000 <__data_start> ; R_AARCH64_ADR_PREL_PG_HI21 var1 754: 91004000 add x0, x0, #0x10 ; R_AARCH64_ADD_ABS_LO12_NC var1 758: b9400001 ldr w1, [x0] 75c: 90000080 adrp x0, 10000 <__FRAME_END__+0xf7bc> ; R_AARCH64_ADR_GOT_PAGE var2 760: f947e800 ldr x0, [x0, #4048] ; R_AARCH64_LD64_GOT_LO12_NC var2 764: b9400002 ldr w2, [x0] 768: 90000000 adrp x0, 0 <_init-0x5b0> ; R_AARCH64_ADR_PREL_PG_HI21 .rodata 76c: 9120a000 add x0, x0, #0x828 ; R_AARCH64_ADD_ABS_LO12_NC .rodata 770: 97ffffb0 bl 630 <printf@plt> ; R_AARCH64_CALL26 printf 774: d503201f nop 778: a8c17bfd ldp x29, x30, [sp], #16 77c: d65f03c0 ret
다음 .plt 섹션에는 런타임에 외부 공유 라이브러리와의 연결에 사용되는 .got 섹션의 엔트리들을 가리키도록 코드가 생성된다.
- 실행파일내의 모든 printf() 호출 부분은 printf@plt 레이블에 생성된 코드를 통한다.
$ objdump -d -D test Disassembly of section .plt: (...생략...) 0000000000000620 <abort@plt>: (...생략...) 0000000000000630 <printf@plt>: 630: 90000090 adrp x16, 10000 <printf@plt+0xf9d0> 634: f947da11 ldr x17, [x16, #4016] 638: 913ec210 add x16, x16, #0xfb0 63c: d61f0220 br x17
외부 공유 라이브러리에 존재하는 printf() 함수를 호출한다.
- .got 섹션에 있는 .got 엔트리중 0x10fb0 offset 주소에 담긴 외부 printf() 주소를 x17에 알아온 후 이 루틴을 호출한다.
다음 .got 섹션에는 외부 공유 라이브러리와 함수 또는 변수의 절대 주소를 담고 있다.
- 아래 값은 실행파일이 로드될 때 주 메모리에서만 엔트리가 갱신된다.
Disassembly of section .got: 0000000000010f78 <.got>: ... 10fb0: 000005d0 .inst 0x000005d0 ; undefined 10fb4: 00000000 .inst 0x00000000 ; undefined
main 실행 파일 로드 후의 디스어셈블 코드
다음은 실행 파일을 로드한 후 동작하기 직전의 디스어셈블 코드이다.
- 모든 offset 로드된 가상 주소로 변경되었다.
- got 엔트리의 printf() 함수에 대한 주소가 0x7ff7ec49a0로 변경되어 있음을 알 수 있다.
Disassembly of section .plt: 0x0000005555555630 <printf@plt>: 0x0000005555555630 <+0>: adrp x16, 0x5555565000 0x0000005555555634 <+4>: ldr x17, [x16, #4016] 0x0000005555555638 <+8>: add x16, x16, #0xfb0 0x000000555555563c <+12>: br x17 Disassembly of section .text: 0x0000005555555744 <main>: 0x0000005555555744 <+0>: stp x29, x30, [sp, #-16]! 0x0000005555555748 <+4>: mov x29, sp 0x000000555555574c <+8>: bl 0x5555555780 <sub1> 0x0000005555555750 <+12>: adrp x0, 0x5555566000 0x0000005555555754 <+16>: add x0, x0, #0x10 0x0000005555555758 <+20>: ldr w1, [x0] 0x000000555555575c <+24>: adrp x0, 0x5555565000 0x0000005555555760 <+28>: ldr x0, [x0, #4048] 0x0000005555555764 <+32>: ldr w2, [x0] 0x0000005555555768 <+36>: adrp x0, 0x5555555000 0x000000555555576c <+40>: add x0, x0, #0x828 0x0000005555555770 <+44>: bl 0x5555555630 <printf@plt> 0x0000005555555774 <+48>: nop 0x0000005555555778 <+52>: ldp x29, x30, [sp], #16 0x000000555555577c <+56>: ret Disassembly of section .got: 0x0000005555565f78 <.got>: ... 0x0000005555565fb0: 0xf7ec49a0 .inst 0xf7ec49a0 0x0000005555565fb8: 0x0000007f .inst 0x0000007f ...
head.o 주소 참조부 ELF 분석
다음은 커널의 어셈블리 파트 시작을 담당하는 head.S를 어셈블한 파일의 섹션들을 살펴본다.
$ readelf -S head.o There are 29 section headers, starting at offset 0x22350: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 1 [ 2] .data PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 WA 0 0 1 [ 3] .bss NOBITS 0000000000000000 00000040 0000000000000000 0000000000000000 WA 0 0 1 [ 4] .head.text PROGBITS 0000000000000000 00010000 0000000000010000 0000000000000000 AX 0 0 65536 [ 5] .rela.head.text RELA 0000000000000000 00021720 0000000000000180 0000000000000018 I 26 4 8 [ 6] .init.text PROGBITS 0000000000000000 00020000 00000000000003a8 0000000000000000 AX 0 0 4 [ 7] .rela.init.text RELA 0000000000000000 000218a0 00000000000004e0 0000000000000018 I 26 6 8 [ 8] .rodata PROGBITS 0000000000000000 000203a8 0000000000000008 0000000000000000 A 0 0 1 [ 9] .rela.rodata RELA 0000000000000000 00021d80 0000000000000018 0000000000000018 I 26 8 8 [10] ___ksymtab+kimage PROGBITS 0000000000000000 000203b0 000000000000000c 0000000000000000 A 0 0 4 [11] .rela___ksymtab+k RELA 0000000000000000 00021d98 0000000000000030 0000000000000018 I 26 10 8 [12] __ksymtab_strings PROGBITS 0000000000000000 000203bc 000000000000000d 0000000000000001 AMS 0 0 1 [13] .idmap.text PROGBITS 0000000000000000 000203d0 0000000000000340 0000000000000000 WAX 0 0 8 [14] .rela.idmap.text RELA 0000000000000000 00021dc8 00000000000002b8 0000000000000018 I 26 13 8 [15] .mmuoff.data.writ PROGBITS 0000000000000000 00020710 0000000000000010 0000000000000000 WA 0 0 1 [16] .debug_line PROGBITS 0000000000000000 00020720 000000000000019b 0000000000000000 0 0 1 [17] .rela.debug_line RELA 0000000000000000 00022080 0000000000000048 0000000000000018 I 26 16 8 [18] .debug_info PROGBITS 0000000000000000 000208bb 0000000000000022 0000000000000000 0 0 1 [19] .rela.debug_info RELA 0000000000000000 000220c8 0000000000000090 0000000000000018 I 26 18 8 [20] .debug_abbrev PROGBITS 0000000000000000 000208dd 0000000000000012 0000000000000000 0 0 1 [21] .debug_aranges PROGBITS 0000000000000000 000208f0 0000000000000050 0000000000000000 0 0 16 [22] .rela.debug_arang RELA 0000000000000000 00022158 0000000000000060 0000000000000018 I 26 21 8 [23] .debug_str PROGBITS 0000000000000000 00020940 0000000000000040 0000000000000001 MS 0 0 1 [24] .debug_ranges PROGBITS 0000000000000000 00020980 0000000000000050 0000000000000000 0 0 16 [25] .rela.debug_range RELA 0000000000000000 000221b8 0000000000000090 0000000000000018 I 26 24 8 [26] .symtab SYMTAB 0000000000000000 000209d0 0000000000000900 0000000000000018 27 48 8 [27] .strtab STRTAB 0000000000000000 000212d0 0000000000000450 0000000000000000 0 0 1 [28] .shstrtab STRTAB 0000000000000000 00022248 0000000000000108 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), p (processor specific)
head.S에서 주소 참조된 엔트리들을 살펴본다.
$ objdump -r head.o head.o: file format elf64-littleaarch64 RELOCATION RECORDS FOR [.head.text]: OFFSET TYPE VALUE 0000000000000004 R_AARCH64_JUMP26 primary_entry 0000000000000010 R_AARCH64_ABS32 _kernel_size_le_lo32 0000000000000014 R_AARCH64_ABS32 _kernel_size_le_hi32 0000000000000018 R_AARCH64_ABS32 _kernel_flags_le_lo32 000000000000001c R_AARCH64_ABS32 _kernel_flags_le_hi32 000000000000005c R_AARCH64_PREL32 __initdata_begin-0x000000000000ffa4 0000000000000060 R_AARCH64_ABS32 __pecoff_data_size 0000000000000068 R_AARCH64_PREL32 __efistub_efi_pe_entry+0x0000000000000068 000000000000007c R_AARCH64_ABS32 PECOFF_FILE_ALIGNMENT 0000000000000090 R_AARCH64_PREL32 _end+0x0000000000000090 0000000000000100 R_AARCH64_PREL32 __initdata_begin-0x000000000000ff00 0000000000000108 R_AARCH64_PREL32 __initdata_begin-0x000000000000fef8 0000000000000128 R_AARCH64_ABS32 __pecoff_data_size 000000000000012c R_AARCH64_PREL32 __initdata_begin+0x000000000000012c 0000000000000130 R_AARCH64_ABS32 __pecoff_data_rawsize 0000000000000134 R_AARCH64_PREL32 __initdata_begin+0x0000000000000134 RELOCATION RECORDS FOR [.init.text]: OFFSET TYPE VALUE 0000000000000004 R_AARCH64_CALL26 el2_setup 0000000000000008 R_AARCH64_ADR_PREL_PG_HI21 _text 0000000000000010 R_AARCH64_CALL26 .idmap.text+0x0000000000000180 0000000000000018 R_AARCH64_CALL26 __cpu_setup 000000000000001c R_AARCH64_JUMP26 .idmap.text+0x0000000000000310 0000000000000024 R_AARCH64_ADR_PREL_PG_HI21 boot_args 0000000000000028 R_AARCH64_ADD_ABS_LO12_NC boot_args 000000000000003c R_AARCH64_JUMP26 __inval_dcache_area 0000000000000044 R_AARCH64_ADR_PREL_PG_HI21 init_pg_dir 0000000000000048 R_AARCH64_ADR_PREL_PG_HI21 init_pg_end 0000000000000050 R_AARCH64_CALL26 __inval_dcache_area 0000000000000054 R_AARCH64_ADR_PREL_PG_HI21 init_pg_dir 0000000000000058 R_AARCH64_ADR_PREL_PG_HI21 init_pg_end 000000000000007c R_AARCH64_ADR_PREL_PG_HI21 idmap_pg_dir 0000000000000080 R_AARCH64_ADR_PREL_PG_HI21 __idmap_text_start 0000000000000088 R_AARCH64_ADR_PREL_PG_HI21 vabits_actual 000000000000008c R_AARCH64_ADD_ABS_LO12_NC vabits_actual 000000000000009c R_AARCH64_ADR_PREL_PG_HI21 __idmap_text_end 00000000000000ac R_AARCH64_ADR_PREL_PG_HI21 idmap_t0sz 00000000000000b0 R_AARCH64_ADD_ABS_LO12_NC idmap_t0sz 00000000000000c4 R_AARCH64_ADR_PREL_PG_HI21 idmap_ptrs_per_pgd 00000000000000c8 R_AARCH64_LDST64_ABS_LO12_NC idmap_ptrs_per_pgd 00000000000000cc R_AARCH64_ADR_PREL_PG_HI21 idmap_ptrs_per_pgd 00000000000000d0 R_AARCH64_LDST64_ABS_LO12_NC idmap_ptrs_per_pgd 00000000000000d8 R_AARCH64_ADR_PREL_PG_HI21 __idmap_text_end 00000000000000dc R_AARCH64_ADD_ABS_LO12_NC __idmap_text_end 00000000000001e0 R_AARCH64_ADR_PREL_PG_HI21 init_pg_dir 00000000000001f8 R_AARCH64_ADR_PREL_PG_HI21 _end 00000000000001fc R_AARCH64_ADR_PREL_PG_HI21 _text 000000000000030c R_AARCH64_ADR_PREL_PG_HI21 idmap_pg_dir 0000000000000310 R_AARCH64_ADR_PREL_PG_HI21 idmap_pg_end 0000000000000318 R_AARCH64_CALL26 __inval_dcache_area 000000000000031c R_AARCH64_ADR_PREL_PG_HI21 init_pg_dir 0000000000000320 R_AARCH64_ADR_PREL_PG_HI21 init_pg_end 0000000000000328 R_AARCH64_CALL26 __inval_dcache_area 0000000000000330 R_AARCH64_ADR_PREL_PG_HI21 init_thread_union 0000000000000338 R_AARCH64_ADR_PREL_PG_HI21 init_task 000000000000033c R_AARCH64_ADD_ABS_LO12_NC init_task 0000000000000344 R_AARCH64_ADR_PREL_PG_HI21 vectors 0000000000000348 R_AARCH64_ADD_ABS_LO12_NC vectors 000000000000035c R_AARCH64_ADR_PREL_PG_HI21 __fdt_pointer 0000000000000360 R_AARCH64_LDST64_ABS_LO12_NC __fdt_pointer 0000000000000364 R_AARCH64_ADR_PREL_PG_HI21 kimage_vaddr 0000000000000368 R_AARCH64_LDST64_ABS_LO12_NC kimage_vaddr 0000000000000370 R_AARCH64_ADR_PREL_PG_HI21 kimage_voffset 0000000000000374 R_AARCH64_LDST64_ABS_LO12_NC kimage_voffset 0000000000000378 R_AARCH64_ADR_PREL_PG_HI21 __bss_start 000000000000037c R_AARCH64_ADD_ABS_LO12_NC __bss_start 0000000000000384 R_AARCH64_ADR_PREL_PG_HI21 __bss_stop 0000000000000388 R_AARCH64_ADD_ABS_LO12_NC __bss_stop 0000000000000390 R_AARCH64_CALL26 __pi_memset 00000000000003a4 R_AARCH64_JUMP26 start_kernel RELOCATION RECORDS FOR [.rodata]: OFFSET TYPE VALUE 0000000000000000 R_AARCH64_ABS64 _text RELOCATION RECORDS FOR [___ksymtab+kimage_vaddr]: OFFSET TYPE VALUE 0000000000000000 R_AARCH64_PREL32 kimage_vaddr 0000000000000004 R_AARCH64_PREL32 __kstrtab_kimage_vaddr RELOCATION RECORDS FOR [.idmap.text]: OFFSET TYPE VALUE 0000000000000160 R_AARCH64_ADR_PREL_PG_HI21 __hyp_stub_vectors 0000000000000164 R_AARCH64_ADD_ABS_LO12_NC __hyp_stub_vectors 0000000000000180 R_AARCH64_ADR_PREL_PG_HI21 __boot_cpu_mode 0000000000000184 R_AARCH64_ADD_ABS_LO12_NC __boot_cpu_mode 00000000000001a4 R_AARCH64_CALL26 el2_setup 00000000000001c0 R_AARCH64_ADR_PREL_PG_HI21 secondary_holding_pen_release 00000000000001c4 R_AARCH64_ADD_ABS_LO12_NC secondary_holding_pen_release 00000000000001dc R_AARCH64_CALL26 el2_setup 00000000000001e8 R_AARCH64_CALL26 __cpu_secondary_check52bitva 00000000000001ec R_AARCH64_CALL26 __cpu_setup 00000000000001f0 R_AARCH64_ADR_PREL_PG_HI21 swapper_pg_dir 00000000000001f4 R_AARCH64_CALL26 __enable_mmu 0000000000000200 R_AARCH64_ADR_PREL_PG_HI21 vectors 0000000000000204 R_AARCH64_ADD_ABS_LO12_NC vectors 0000000000000210 R_AARCH64_ADR_PREL_PG_HI21 secondary_data 0000000000000214 R_AARCH64_ADD_ABS_LO12_NC secondary_data 0000000000000238 R_AARCH64_JUMP26 secondary_start_kernel 000000000000025c R_AARCH64_ADR_PREL_PG_HI21 __early_cpu_boot_status 0000000000000260 R_AARCH64_ADD_ABS_LO12_NC __early_cpu_boot_status 0000000000000270 R_AARCH64_ADR_PREL_PG_HI21 idmap_pg_dir 00000000000002a8 R_AARCH64_ADR_PREL_PG_HI21 __early_cpu_boot_status 00000000000002ac R_AARCH64_ADD_ABS_LO12_NC __early_cpu_boot_status 0000000000000310 R_AARCH64_ADR_PREL_PG_HI21 init_pg_dir 0000000000000314 R_AARCH64_CALL26 __enable_mmu 0000000000000320 R_AARCH64_ADR_PREL_PG_HI21 _text 0000000000000328 R_AARCH64_ABS32 __rela_offset 000000000000032c R_AARCH64_ABS32 __rela_size 0000000000000330 R_AARCH64_ABS64 .idmap.text+0x0000000000000200 0000000000000338 R_AARCH64_ABS64 .init.text+0x0000000000000330 RELOCATION RECORDS FOR [.debug_line]: OFFSET TYPE VALUE 000000000000003c R_AARCH64_ABS64 .head.text 0000000000000052 R_AARCH64_ABS64 .init.text 00000000000000d1 R_AARCH64_ABS64 .idmap.text RELOCATION RECORDS FOR [.debug_info]: OFFSET TYPE VALUE 0000000000000006 R_AARCH64_ABS32 .debug_abbrev 000000000000000c R_AARCH64_ABS32 .debug_line 0000000000000010 R_AARCH64_ABS32 .debug_ranges 0000000000000014 R_AARCH64_ABS32 .debug_str 0000000000000018 R_AARCH64_ABS32 .debug_str+0x0000000000000019 000000000000001c R_AARCH64_ABS32 .debug_str+0x0000000000000034 RELOCATION RECORDS FOR [.debug_aranges]: OFFSET TYPE VALUE 0000000000000006 R_AARCH64_ABS32 .debug_info 0000000000000010 R_AARCH64_ABS64 .head.text 0000000000000020 R_AARCH64_ABS64 .init.text 0000000000000030 R_AARCH64_ABS64 .idmap.text RELOCATION RECORDS FOR [.debug_ranges]: OFFSET TYPE VALUE 0000000000000010 R_AARCH64_ABS64 .head.text 0000000000000018 R_AARCH64_ABS64 .head.text+0x0000000000010000 0000000000000020 R_AARCH64_ABS64 .init.text 0000000000000028 R_AARCH64_ABS64 .init.text+0x00000000000003a8 0000000000000030 R_AARCH64_ABS64 .idmap.text 0000000000000038 R_AARCH64_ABS64 .idmap.text+0x0000000000000340
ELF64 포맷 분석
간단한 어셈블리 샘플 프로그램 test.S
.text .globl _start .align 2 _start: adrp x0, msg add x0, x0, :lo12:msg // 어셈블 타임에 msg2 주소의 하위 12비트를 취해 더함. adr x1, msg ldr x2, msg ldr x3, =msg /* sys_exit 코드 */ mov x0, 123 mov x8, 93 svc #0 .data msg: .quad 10
위의 test.S를 빌드한 후 hexdump 한 값들을 보여준다.
$ hexdump -S test [ELF Header] 00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| 00000010 02 00 b7 00 01 00 00 00 b0 00 40 00 00 00 00 00 |..........@.....| 00000020 40 00 00 00 00 00 00 00 58 04 00 00 00 00 00 00 |@.......X.......| 00000030 00 00 00 00 40 00 38 00 02 00 40 00 0b 00 0a 00 |....@.8...@.....| [Program Header] [0] 00000040 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 |..@.......@.....| 00000060 d8 00 00 00 00 00 00 00 d8 00 00 00 00 00 00 00 |................| 00000070 00 00 01 00 00 00 00 00 [1] 01 00 00 00 06 00 00 00 |................| 00000080 d8 00 00 00 00 00 00 00 d8 00 41 00 00 00 00 00 |..........A.....| 00000090 d8 00 41 00 00 00 00 00 04 00 00 00 00 00 00 00 |..A.............| 000000a0 04 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 |................| [Section] [.text: virt=0x4000b0] 000000b0 80 00 00 90 00 60 03 91 01 01 08 10 e2 00 08 58 |.....`.........X| 000000c0 83 00 00 58 60 0f 80 d2 a8 0b 80 d2 01 00 00 d4 |...X`...........| 000000d0 d8 00 41 00 00 00 00 00 [.data: virt=0x4100d8] 000000d8 0a 00 00 00 00 00 00 00 |..A.............| [.debug_arranges] 000000e0 2c 00 00 00 02 00 00 00 00 00 08 00 00 00 00 00 |,...............| 000000f0 b0 00 40 00 00 00 00 00 28 00 00 00 00 00 00 00 |..@.....(.......| 00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| [.debug_info] 00000110 2a 00 00 00 02 00 00 00 00 00 08 01 00 00 00 00 |*...............| 00000120 b0 00 40 00 00 00 00 00 d8 00 40 00 00 00 00 00 |..@.......@.....| 00000130 00 00 00 00 07 00 00 00 21 00 00 00 01 80 [.debug_abbrev] 01 11 |........!.......| 00000140 00 10 06 11 01 12 01 03 0e 1b 0e 25 0e 13 05 00 |...........%....| 00000150 00 00 [.debug_line] 3b 00 00 00 02 00 1d 00 00 00 04 01 fb 0e |..;.............| 00000160 0d 00 01 01 01 01 00 00 00 01 00 00 01 00 74 65 |..............te| 00000170 73 74 2e 53 00 00 00 00 00 00 09 02 b0 00 40 00 |st.S..........@.| 00000180 00 00 00 00 17 21 22 22 22 23 21 21 02 03 00 01 |.....!"""#!!....| 00000190 01 [.debug_str] 74 65 73 74 2e 53 00 2f 72 6f 6f 74 2f 77 6f |.test.S./root/wo| 000001a0 72 6b 73 70 61 63 65 2f 74 65 73 74 2f 61 73 6d |rkspace/test/asm| 000001b0 35 00 47 4e 55 20 41 53 20 32 2e 33 30 00 [.symtab] 00 00 |5.GNU AS 2.30...| 000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 03 00 01 00 |................| 000001e0 b0 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 000001f0 00 00 00 00 03 00 02 00 d8 00 41 00 00 00 00 00 |..........A.....| 00000200 00 00 00 00 00 00 00 00 00 00 00 00 03 00 03 00 |................| 00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000220 00 00 00 00 03 00 04 00 00 00 00 00 00 00 00 00 |................| 00000230 00 00 00 00 00 00 00 00 00 00 00 00 03 00 05 00 |................| 00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000250 00 00 00 00 03 00 06 00 00 00 00 00 00 00 00 00 |................| 00000260 00 00 00 00 00 00 00 00 00 00 00 00 03 00 07 00 |................| 00000270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000280 01 00 00 00 04 00 f1 ff 00 00 00 00 00 00 00 00 |................| 00000290 00 00 00 00 00 00 00 00 08 00 00 00 00 00 01 00 |................| 000002a0 b0 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 000002b0 0b 00 00 00 00 00 02 00 d8 00 41 00 00 00 00 00 |..........A.....| 000002c0 00 00 00 00 00 00 00 00 0f 00 00 00 00 00 01 00 |................| 000002d0 d0 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 000002e0 21 00 00 00 10 00 02 00 dc 00 41 00 00 00 00 00 |!.........A.....| 000002f0 00 00 00 00 00 00 00 00 12 00 00 00 10 00 02 00 |................| 00000300 dc 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00 |..A.............| 00000310 20 00 00 00 10 00 02 00 dc 00 41 00 00 00 00 00 | .........A.....| 00000320 00 00 00 00 00 00 00 00 31 00 00 00 10 00 01 00 |........1.......| 00000330 b0 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............| 00000340 2c 00 00 00 10 00 02 00 dc 00 41 00 00 00 00 00 |,.........A.....| 00000350 00 00 00 00 00 00 00 00 38 00 00 00 10 00 02 00 |........8.......| 00000360 e0 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00 |..A.............| 00000370 40 00 00 00 10 00 02 00 dc 00 41 00 00 00 00 00 |@.........A.....| 00000380 00 00 00 00 00 00 00 00 47 00 00 00 10 00 02 00 |........G.......| 00000390 e0 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00 |..A.............| 000003a0 00 74 65 73 74 2e 6f 00 24 78 00 6d 73 67 00 24 |.test.o.$x.msg.$| 000003b0 64 00 5f 5f 62 73 73 5f 73 74 61 72 74 5f 5f 00 |d.__bss_start__.| 000003c0 5f 5f 62 73 73 5f 65 6e 64 5f 5f 00 5f 5f 62 73 |__bss_end__.__bs| 000003d0 73 5f 73 74 61 72 74 00 5f 5f 65 6e 64 5f 5f 00 |s_start.__end__.| 000003e0 5f 65 64 61 74 61 00 5f 65 6e 64 00 00 2e 73 79 |_edata._end...sy| 000003f0 6d 74 61 62 00 2e 73 74 72 74 61 62 00 2e 73 68 |mtab..strtab..sh| 00000400 73 74 72 74 61 62 00 2e 74 65 78 74 00 2e 64 61 |strtab..text..da| 00000410 74 61 00 2e 64 65 62 75 67 5f 61 72 61 6e 67 65 |ta..debug_arange| 00000420 73 00 2e 64 65 62 75 67 5f 69 6e 66 6f 00 2e 64 |s..debug_info..d| 00000430 65 62 75 67 5f 61 62 62 72 65 76 00 2e 64 65 62 |ebug_abbrev..deb| 00000440 75 67 5f 6c 69 6e 65 00 2e 64 65 62 75 67 5f 73 |ug_line..debug_s| 00000450 74 72 00 00 00 00 00 00 |tr...... [Section Header] 00000458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000498 1b 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00 |................| 000004a8 b0 00 40 00 00 00 00 00 b0 00 00 00 00 00 00 00 |..@.............| 000004b8 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |(...............| 000004c8 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000004d8 21 00 00 00 01 00 00 00 03 00 00 00 00 00 00 00 |!...............| 000004e8 d8 00 41 00 00 00 00 00 d8 00 00 00 00 00 00 00 |..A.............| 000004f8 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000508 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000518 27 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |'...............| 00000528 00 00 00 00 00 00 00 00 e0 00 00 00 00 00 00 00 |................| 00000538 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |0...............| 00000548 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000558 36 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |6...............| 00000568 00 00 00 00 00 00 00 00 10 01 00 00 00 00 00 00 |................| 00000578 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000588 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000598 42 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |B...............| 000005a8 00 00 00 00 00 00 00 00 3e 01 00 00 00 00 00 00 |........>.......| 000005b8 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000005c8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000005d8 50 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 |P...............| 000005e8 00 00 00 00 00 00 00 00 52 01 00 00 00 00 00 00 |........R.......| 000005f8 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |?...............| 00000608 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000618 5c 00 00 00 01 00 00 00 30 00 00 00 00 00 00 00 |\.......0.......| 00000628 00 00 00 00 00 00 00 00 91 01 00 00 00 00 00 00 |................| 00000638 2d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |-...............| 00000648 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| 00000658 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................| 00000668 00 00 00 00 00 00 00 00 c0 01 00 00 00 00 00 00 |................| 00000678 e0 01 00 00 00 00 00 00 09 00 00 00 0c 00 00 00 |................| 00000688 08 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00 |................| 00000698 09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| 000006a8 00 00 00 00 00 00 00 00 a0 03 00 00 00 00 00 00 |................| 000006b8 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |L...............| 000006c8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000006d8 11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 |................| 000006e8 00 00 00 00 00 00 00 00 ec 03 00 00 00 00 00 00 |................| 000006f8 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |g...............| 00000708 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000718
다음은 위의 test 파일에 대해 자세히 출력한다.
$ readelf -a test ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: AArch64 Version: 0x1 Entry point address: 0x4000b0 Start of program headers: 64 (bytes into file) Start of section headers: 1112 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 2 Size of section headers: 64 (bytes) Number of section headers: 11 Section header string table index: 10 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 00000000004000b0 000000b0 0000000000000028 0000000000000000 AX 0 0 8 [ 2] .data PROGBITS 00000000004100d8 000000d8 0000000000000004 0000000000000000 WA 0 0 1 [ 3] .debug_aranges PROGBITS 0000000000000000 000000e0 0000000000000030 0000000000000000 0 0 16 [ 4] .debug_info PROGBITS 0000000000000000 00000110 000000000000002e 0000000000000000 0 0 1 [ 5] .debug_abbrev PROGBITS 0000000000000000 0000013e 0000000000000014 0000000000000000 0 0 1 [ 6] .debug_line PROGBITS 0000000000000000 00000152 000000000000003f 0000000000000000 0 0 1 [ 7] .debug_str PROGBITS 0000000000000000 00000191 000000000000002d 0000000000000001 MS 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 000001c0 00000000000001e0 0000000000000018 9 12 8 [ 9] .strtab STRTAB 0000000000000000 000003a0 000000000000004c 0000000000000000 0 0 1 [10] .shstrtab STRTAB 0000000000000000 000003ec 0000000000000067 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000000d8 0x00000000000000d8 R E 0x10000 LOAD 0x00000000000000d8 0x00000000004100d8 0x00000000004100d8 0x0000000000000004 0x0000000000000004 RW 0x10000 Section to Segment mapping: Segment Sections... 00 .text 01 .data There is no dynamic section in this file. There are no relocations in this file. The decoding of unwind sections for machine type AArch64 is not currently supported. Symbol table '.symtab' contains 20 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000004000b0 0 SECTION LOCAL DEFAULT 1 2: 00000000004100d8 0 SECTION LOCAL DEFAULT 2 3: 0000000000000000 0 SECTION LOCAL DEFAULT 3 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 5: 0000000000000000 0 SECTION LOCAL DEFAULT 5 6: 0000000000000000 0 SECTION LOCAL DEFAULT 6 7: 0000000000000000 0 SECTION LOCAL DEFAULT 7 8: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.o 9: 00000000004000b0 0 NOTYPE LOCAL DEFAULT 1 $x 10: 00000000004100d8 0 NOTYPE LOCAL DEFAULT 2 msg 11: 00000000004000d0 0 NOTYPE LOCAL DEFAULT 1 $d 12: 00000000004100dc 0 NOTYPE GLOBAL DEFAULT 2 _bss_end__ 13: 00000000004100dc 0 NOTYPE GLOBAL DEFAULT 2 __bss_start__ 14: 00000000004100dc 0 NOTYPE GLOBAL DEFAULT 2 __bss_end__ 15: 00000000004000b0 0 NOTYPE GLOBAL DEFAULT 1 _start 16: 00000000004100dc 0 NOTYPE GLOBAL DEFAULT 2 __bss_start 17: 00000000004100e0 0 NOTYPE GLOBAL DEFAULT 2 __end__ 18: 00000000004100dc 0 NOTYPE GLOBAL DEFAULT 2 _edata 19: 00000000004100e0 0 NOTYPE GLOBAL DEFAULT 2 _end No version information found in this file.
구조체
elf32_hdr 구조체 – ELF32 헤더
glibc/elf/elf.h
typedef struct elf32_hdr{ unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr;
elf64_hdr 구조체 – ELF64 헤더
glibc/elf/elf.h
typedef struct elf64_hdr { unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; /* Entry point virtual address */ Elf64_Off e_phoff; /* Program header table file offset */ Elf64_Off e_shoff; /* Section header table file offset */ Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;
Elf32_Shdr – ELF32 섹션 헤더
glibc/elf/elf.h
typedef struct { Elf32_Word sh_name; /* Section name (string tbl index) */ Elf32_Word sh_type; /* Section type */ Elf32_Word sh_flags; /* Section flags */ Elf32_Addr sh_addr; /* Section virtual addr at execution */ Elf32_Off sh_offset; /* Section file offset */ Elf32_Word sh_size; /* Section size in bytes */ Elf32_Word sh_link; /* Link to another section */ Elf32_Word sh_info; /* Additional section information */ Elf32_Word sh_addralign; /* Section alignment */ Elf32_Word sh_entsize; /* Entry size if section holds table */ } Elf32_Shdr;
Elf32_Shdr – ELF64 섹션 헤더
glibc/elf/elf.h
typedef struct { Elf64_Word sh_name; /* Section name (string tbl index) */ Elf64_Word sh_type; /* Section type */ Elf64_Xword sh_flags; /* Section flags */ Elf64_Addr sh_addr; /* Section virtual addr at execution */ Elf64_Off sh_offset; /* Section file offset */ Elf64_Xword sh_size; /* Section size in bytes */ Elf64_Word sh_link; /* Link to another section */ Elf64_Word sh_info; /* Additional section information */ Elf64_Xword sh_addralign; /* Section alignment */ Elf64_Xword sh_entsize; /* Entry size if section holds table */ } Elf64_Shdr;
Elf32_Phdr – ELF32 프로그램 헤더
glibc/elf/elf.h
typedef struct { Elf32_Word p_type; /* Segment type */ Elf32_Off p_offset; /* Segment file offset */ Elf32_Addr p_vaddr; /* Segment virtual address */ Elf32_Addr p_paddr; /* Segment physical address */ Elf32_Word p_filesz; /* Segment size in file */ Elf32_Word p_memsz; /* Segment size in memory */ Elf32_Word p_flags; /* Segment flags */ Elf32_Word p_align; /* Segment alignment */ } Elf32_Phdr;
Elf32_Phdr – ELF64 프로그램 헤더
glibc/elf/elf.h
typedef struct { Elf64_Word p_type; /* Segment type */ Elf64_Word p_flags; /* Segment flags */ Elf64_Off p_offset; /* Segment file offset */ Elf64_Addr p_vaddr; /* Segment virtual address */ Elf64_Addr p_paddr; /* Segment physical address */ Elf64_Xword p_filesz; /* Segment size in file */ Elf64_Xword p_memsz; /* Segment size in memory */ Elf64_Xword p_align; /* Segment alignment */ } Elf64_Phdr;
참고
- Relocations: fantastic symbols, but where to find them? (2020) | Hell Oh Entropy
- ELF for the ARM 64-bit Architecture (AArch64, 2013) | 다운로드 pdf
- PLT와 GOT 자세히 알기 1 (for x86)| Hackerz on the Ship
- PLT와 GOT 자세히 알기 2 (with ‘yocto’) (for x86) | Hackerz on the Ship
- ARMv8-A + ELF64 바이너리 Radare2로 PLT 호출 분석하기 | 커널리스트