엘프 헤더, 프로그램 헤더, 섹션, 세그먼트 등을 포함하여 이 모든 것을 알려주는 ELF 형식 사양을 읽고 있습니다. 이들 모두는 다양한 필드와 값을 갖는 구조로 참조됩니다.
그렇다면 문제는 이 모든 것이 어디로 가는가입니다. 내 말은, readelf
util의 출력 대신 구조로 처리할 수 있습니까 ?
이 모든 것이 포함된 중간 파일이 있습니까?엘프 마법존재하고 소스 코드에 병합되었나요? 아니면 단지 컴파일러의 내부 구조이고 그 구조는 인간만을 위한 사양서에 언급되어 있는 걸까요? )
나에게 이것은 "닭과 달걀 문제"(컴파일된 코드에 대해 이야기하기 위해 코드를 사용하는 것)처럼 보입니다.
답변1
이러한 구조는 ELF 파일에 존재합니다.
ELF 헤더를 살펴보겠습니다.
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file 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; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
ELF 헤더는 다음 위치에 있습니다.모든ELF 파일.
이것이 실제로 의미하는 바는 ELF 파일의 처음 16바이트가 e_ident
ELF 헤더의 필드라는 것입니다.
첫 번째 바이트는 0x7f입니다.
두 번째는
'E'
;세 번째는
'L'
;네 번째는
'F'
;다섯 번째는 수업입니다.
여섯 번째는 데이터 인코딩입니다.
일곱 번째는 파일 버전입니다.
여덟 번째는 운영 체제 ABI입니다.
등.
이 필드 e_ident
다음의 2바이트는 입니다 e_type
.
그게 당신이라면 시작 부분에 가까운 것을 head /bin/bash
볼 수 있을 것입니다 .ELF
이제 ELF 파일 시작 부분의 16진 덤프를 얻으면:
$ xxd /bin/bash | xxd 헤더 | 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF.............. 00000010: 0200 3e00 0100 0000 7005 4200 0000 0000 ..>.....pB.... 00000020: 4000 0000 0000 0000 c0cd 0f00 0000 0000 @........... 00000030: 0000 0000 4000 3800 0900 4000 1d00 1c00 [이메일 보호됨]...@..... 00000040: 0600 0000 0500 0000 4000 0000 0000 0000 .......@....... 00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@..... 00000060: f801 0000 0000 0000 f801 0000 0000 0000 ........ 00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ............ 00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@..... 00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@........................
이 16진수 덤프의 첫 번째 줄은 처음 16바이트( e_ident
)입니다.
첫 번째 바이트는 실제로
0x7f
;그러다가
"ELF"
;그 다음에는 (ELF64)
0x02
클래스가 있습니다.ELFCLASS64
0x01
그런 다음 인코딩이 옵니다ELFDATA2LSB
.등.
두 번째 줄의 처음 2바이트는 입니다 e_type
. LSB로 인코딩되므로(때문에 ELFDATA2LSB
) 값은 실제로 는 실행 파일임을 0x0002
의미합니다 .ET_EXEC
다음 2바이트는 아키텍처( e_machine
)입니다. 이는 실행 파일이기 0x003e
때문 입니다 .EM_X86_64
x86_64
ELF 헤더의 모든 필드를 수동으로 디코딩할 수 있어야 하며 주어진 값과 동일한 값을 찾아야 합니다 readelf
. 이를 통해 파일에서 ElfXX_Shdr
또는 와 같은 다른 ELF 구조를 찾아 ElfXX_Phdr
해당 정의에 따라 디코딩할 수 있습니다(주어진 정보와 동일한 정보를 찾아야 합니다 readelf
).
답변2
사용 xxd
하고awk
$ xxd hello_arm64 | awk '{for(i=2;i<NF;i++){a=a$i;c++;if(c>9){print a;exit;}}}'
7f454c460201010000000000000000000200b700
$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags: F
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff