소형 elf "Hello, World" 프로그램

11711 단어 worldhelloelf
참조 링크: http://timelessname.com/elfbin/
 
환경 요구: linux gcc nasm hexcurse (elf 파일 내용 수정 용)
 
먼저 C 언어 로 "Hello, World" 프로그램 을 써 보 세 요.
 
#include <stdio.h>
int main(void)
{
  printf("Hello,World
"); return 0; }
 
다음 명령 으로 컴 파일 하고 실행:
 
[host@myhost linker]$ gcc -o chello chello.c
[host@myhost linker]$ ./chello

 출력 결과:
 
Hello,World

 chello 의 ELF 헤드 부분 을 아래 명령 으로 볼 수 있 습 니 다.
 
readelf -h chello

 출력 결과:
 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048310
  Start of program headers:          52 (bytes into file)
  Start of section headers:          1932 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         30
  Section header string table index: 27

 다음 명령 을 사용 하여 chello 링크 의 동적 링크 라 이브 러 리 를 봅 니 다:
 
ldd chello

  출력 결 과 는:
 
	linux-gate.so.1 =>  (0xb7857000)
	libc.so.6 => /lib/libc.so.6 (0xb76d2000)
	/lib/ld-linux.so.2 (0xb7858000)

  다음 명령 으로 파일 형식 보기:
 
file chello

  출력 결과:
 
chello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped

  다음 명령 을 사용 하여 파일 크기 를 보고 strip 을 사용 하여 기호 표를 꺼 낸 다음 파일 크기 를 봅 니 다.
 
[host@myhost linker]$ ls -l chello
[host@myhost linker]$ strip -s chello
[host@myhost linker]$ ls -l chello
 
 출력 결 과 는:
 
-rwxr-xr-x 1 host users 4746 11   6 23:07 chello
-rwxr-xr-x 1 host users 3036 11   6 23:15 chello

 
다음은 어 셈 블 리 코드 를 사용 하여 이 프로그램 (hello. asm) 을 작성 하고 Liux 인 터 럽 트 를 호출 합 니 다.
 
	SECTION .data
msg:	db "Hello,World",10
len:	equ $-msg

	SECTION .text
	global main
main:
	mov edx,len
	mov ecx,msg
	mov ebx,1
	mov eax,4
	int 0x80
	mov ebx,0
	mov eax,1
	int 0x80

 다음 명령 으로 링크 를 컴 파일 하고 파일 을 만 드 는 기호 표를 꺼 냅 니 다:
 
[host@myhost linker]$ nasm -f elf hello.asm
[host@myhost linker]$ gcc -o hello hello.o -nostartfiles -nostdlib -nodefaultlibs
[host@myhost linker]$ strip -s hello
[host@myhost linker]$ ./hello

 출력 결 과 는:
 
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 08048080
Hello,World

 gcc 명령 을 사용 할 때 경고 가 발생 하지만 이 파일 은 실행 할 수 있 습 니 다. 이 파일 의 크기 는 360 바이트 입 니 다.
"gcc - o hello hello. o - nostartfiles - nostdlib - nodefaultlibs" 명령 을 연결 합 니 다. 영어 주석 은 다음 과 같 습 니 다 링크.
 
-nostartfiles
    Do not use the standard system startup files when linking. The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used.
-nodefaultlibs
    Do not use the standard system libraries when linking. Only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The standard startup files are used normally, unless -nostartfiles is used. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
-nostdlib
    Do not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.

    One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines that GCC uses to overcome shortcomings of particular machines, or special needs for some languages. (See Interfacing to GCC Output, for more discussion of libgcc.a.) In most cases, you need libgcc.a even when you want to avoid other standard libraries. In other words, when you specify -nostdlib or -nodefaultlibs you should usually specify -lgcc as well. This ensures that you have no unresolved references to internal GCC library subroutines. (For example, `__main', used to ensure C++ constructors will be called;

  여기 startupfiles 는 crt0. o (/ lib / crt0. o), crtbegin. o, crtend. o 를 말 합 니 다. crt0. o 는 main 함수 (windows 에서 WinMainCRTStartup 참조 링크 를 호출 하 는 코드 를 포함 하고 있다 고 합 니 다. 여 기 는 어 셈 블 리 코드 를 사용 합 니 다.(c 프로그램 이 라면 crt0. o 를 연결 해 야 합 니 다) 따라서 crt0. o. crtbgin. o 와 crtend. o 를 연결 하지 않 아 도 됩 니 다. c + 구조 와 석조 함 수 를 처리 하 는 데 사용 된다 고 합 니 다. main 함수 로 c 프로그램 을 만 들 지 않 는 다 는 댓 글 Is main required for a c program? 이 있 습 니 다.(사실은 입구 이름 을 바 꾸 는 것 일 뿐 입 니 다. Window 응용 프로그램 이 WinMain 을 입구 함수 로 사용 하 는 것 처럼 자신의 입구 함수 만 사용 할 뿐 관련 처 리 는 모두 스스로 해결 해 야 합 니 다)
다음 명령 을 사용 하여 hello 의 16 진수 설명 을 받 습 니 다:
 
hexdump -x hello

 출력 결과:
 
0000000    457f    464c    0101    0001    0000    0000    0000    0000
0000010    0002    0003    0001    0000    8080    0804    0034    0000
0000020    00c8    0000    0000    0000    0034    0020    0002    0028
0000030    0004    0003    0001    0000    0000    0000    8000    0804
0000040    8000    0804    00a2    0000    00a2    0000    0005    0000
0000050    1000    0000    0001    0000    00a4    0000    90a4    0804
0000060    90a4    0804    000c    0000    000c    0000    0006    0000
0000070    1000    0000    0000    0000    0000    0000    0000    0000
0000080    0cba    0000    b900    90a4    0804    01bb    0000    b800
0000090    0004    0000    80cd    00bb    0000    b800    0001    0000
00000a0    80cd    0000    6548    6c6c    2c6f    6f57    6c72    0a64
00000b0    2e00    6873    7473    7472    6261    2e00    6574    7478
00000c0    2e00    6164    6174    0000    0000    0000    0000    0000
00000d0    0000    0000    0000    0000    0000    0000    0000    0000
*
00000f0    000b    0000    0001    0000    0006    0000    8080    0804
0000100    0080    0000    0022    0000    0000    0000    0000    0000
0000110    0010    0000    0000    0000    0011    0000    0001    0000
0000120    0003    0000    90a4    0804    00a4    0000    000c    0000
0000130    0000    0000    0000    0000    0004    0000    0000    0000
0000140    0001    0000    0003    0000    0000    0000    0000    0000
0000150    00b0    0000    0017    0000    0000    0000    0000    0000
0000160    0001    0000    0000    0000 
 
 이 파일 헤더 (앞의 52 바이트) 를 분석 하면 두 개의 비교적 중요 한 표 의 내용 을 알 수 있다. 첫 번 째 는 프로그램 헤더 (54 (0x 34) 개의 바이트 가 시작 되 고 크기 는 2 * 32 (0x 20) 개의 바이트) 이 며, 다른 하 나 는 세그먼트 헤드 시트 (200 (0xc 8) 개의 바이트 가 시작 되 고 크기 는 2 * 40 (0x 28) 개의 바이트 이다. 그리고 세그먼트 헤드 시트 에 따라 코드 세그먼트 (0x 80 시작 34 바이트 내용) 를 알 수 있다.데이터 세그먼트 (0xa 4 부터 12 바이트 내용) 와 관련 된 정보 입 니 다. 중요 한 것 은 앞의 176 바이트 내용 입 니 다. 이 부분 은 파일 헤더 (52 바이트), 프로그램 헤더 시트 (64 바이트), 공백 내용 (12 바이트), 코드 세그먼트 (34 바이트), 데이터 세그먼트 (12 바이트, Hello, World) 로 나 눌 수 있 습 니 다.
다음 명령 을 사용 하여 hello 의 이전 176 바이트 내용 을 추출 할 수 있 는 권한 을 실행 할 수 있 습 니 다.
 
dd if=hello of=hello.new bs=176 count=1
chmod u+x hello.new 

 파일 hello. new 를 가 져 옵 니 다. 이 파일 을 실행 하면 "Hello, World" 를 얻 을 수 있 습 니 다. 이 파일 은 바 이 너 리 내용 입 니 다.
 
0000000    457f    464c    0101    0001    0000    0000    0000    0000
0000010    0002    0003    0001    0000    8080    0804    0034    0000
0000020    00c8    0000    0000    0000    0034    0020    0002    0028
0000030    0004    0003    0001    0000    0000    0000    8000    0804
0000040    8000    0804    00a2    0000    00a2    0000    0005    0000
0000050    1000    0000    0001    0000    00a4    0000    90a4    0804
0000060    90a4    0804    000c    0000    000c    0000    0006    0000
0000070    1000    0000    0000    0000    0000    0000    0000    0000
0000080    0cba    0000    b900    90a4    0804    01bb    0000    b800
0000090    0004    0000    80cd    00bb    0000    b800    0001    0000
00000a0    80cd    0000    6548    6c6c    2c6f    6f57    6c72    0a64
  
데이터 세그먼트 크기 가 딱 12 이 고 파일 에 12 개의 바이트 공백 이 있 기 때문에 데이터 세그먼트 (0xa 4 에서 시작 하 는 12 개의 글자 분해) 를 공백 으로 옮 길 수 있 습 니 다 (0x 74 에서 시작 하 는 12 개의 바이트)., 0x 86 주소 의 0xa 4 를 0x 74 로 변경 합 니 다. hexcurse hello. new 를 사용 하여 파일 내용 을 수정 한 다음 단축 키 crtl + s 로 저장 하고 hello. res 로 이름 을 바 꿀 수 있 습 니 다. 이 때 hello. res 를 실행 하면 "Hello, World" 를 얻 을 수 있 습 니 다.
그리고 마지막 12 개의 바이트 (명령 dd if = hello. res of = hello. out bs = 164 count = 1) 를 삭제 하고 hello. out 이 마지막 인 결 과 를 얻 을 수 있 습 니 다. 크기 는 164 개의 바이트 입 니 다. 원문 에 따 르 면 이 파일 은 더 압축 할 수 있 지만 코드 세그먼트 의 일부분 을 변경 하고 시간 이 있 을 때 자세히 연구 해 야 합 니 다)
 
Why are DJGPP .exe files so large?
파일 헤더 에는 e entry (0x 18 주소 로 시 작 된 4 개의 바이트 가 있 습 니 다. 값 은 0x 08048080 (0x 08048000 + 0x 80 (코드 세그먼트 오프셋 주소) 입 니 다. 이 주소 에서 명령 을 실행 하 는 것 입 니 다. 코드 세그먼트 (0x 86 에서 시 작 된 4 개의 바이트 (작은 단 법 표시, 9074 0804) 즉 0x 08049074 입 니 다. 이 주 소 는 0x 08048000 + 0x 1000 입 니 다.(코드 세그먼트 가상 주소 가 차지 하 는 공간 크기 는 세그먼트 정렬 이 0x 1000 이기 때문에 최소 4k 크기 (페이지 시스템 에서 각 페이지 의 크기) + 0x 74 입 니 다. 이 주 소 는 원래 주소 0x 080490 a4 입 니 다.(이 주 소 는 원래 의 0x0000005c 와 0x000000060 에서 시 작 된 4 개의 바이트 에 각각 존재 합 니 다. 그러나 0x0000005c 와 0x000000060 의 값 은 업 종 을 바 꾸 지 않 고 정상적으로 작 동 할 수 있 는 것 같 지만 데 이 터 를 일치 시 키 기 위해 서 는 고 치 는 것 이 좋 습 니 다.)
또한 hello. out 은 ELF 헤드, 프로그램 헤드, 코드 세그먼트 와 데이터 세그먼트 만 포함 하고 정상적으로 작 동 할 수 있 으 며 실행 가능 한 파일 중간 헤더 표 (section Header table) 가 옵션 임 을 증명 합 니 다.
 

좋은 웹페이지 즐겨찾기