C 프로그램이 커널에 의해 실행될 때 execve()
,
라는 기본 함수를 호출하기 전에 호출되는 특수 시작 루틴은 어디에 있습니까
execve()
?crt0
execve()
main 함수는 어디에서 호출되나요?
찾을 수 없어요https://elixir.bootlin.com/linux/latest/source/fs/exec.c.
Linux 커널을 이해하는 것부터 시작하여 execve()
내부적으로 실행 파일을 로드할 수 있는 개체를 찾고 linux_binfmt
해당 메서드를 호출하여 로드합니다. 또한 실행 파일에서 사용하는 공유 라이브러리를 로드하고 링크하기 위해 동적 링커를 로드합니다. 하지만 이 책에서는 프로그램의 시작 루틴을 호출한 다음 실행 파일에서 호출하는 방법을 설명하지 않습니다.load_binary()
load_binary()
execve()
crt0
main()
감사해요.
답변1
execve
어떤 커널 코드도 이 함수 _start
(호칭에 관계없이 실행 파일의 진입점)를 호출하지 않습니다.
서로 다른 곳에서 뛰기 때문이죠문맥; 마치 다른 컴퓨터에서 실행되는 것처럼 보입니다.
커널은 execve
사용자 모드로 돌아갈 때 시스템 호출을 예약하고 IP
(명령 포인터) 레지스터를 함수의 시작 부분을 가리키도록 설정 _start
하고 SP
(스택 포인터) 레지스터를 함수의 시작 부분을 가리키도록 설정합니다. argv + env 문자열 목록이므로 사용자 모드 관점에서 효과는 다음과 같습니다.누구이 함수를 _start
다음과 같이 호출하세요.
_start(argc, argv0, argv1, ... , NULL, env0, env1, ... NULL)
모든 인수가 스택에 전달되는 호출 규칙에서.
물론 이런 일이 발생하기 전에 커널은 이미 이러한 argv + env를 올바른 위치에 복사하고 _start
함수가 포함된 세그먼트를 매핑하는 등의 작업을 담당하고 있습니다.
argv + env 문자열은 모두 하나의 블록에 포함되어 있습니다.
"prog\0arg1\0arg2\0VAR1=foo\0VAR2=bar\0"
이 블록이 시작하고 끝나는 가상 주소는 /proc/PID/stat
매뉴얼 procfs(5)
페이지를 인용하여 액세스할 수 있습니다.
(48) arg_start %lu (since Linux 3.5) [PT] Address above which program command-line arguments (argv) are placed. (49) arg_end %lu (since Linux 3.5) [PT] Address below program command-line arguments (argv) are placed.
ps
이 주소에 쓰면 출력에 나타나는 모든 내용이 수정됩니다 .
$ sleep 3600 3600 3600 3600 3600 3600 3600 &
[2] 4927
$ awk '{print $48,$49,$49-$48-1}' /proc/4927/stat
140735402952841 140735402952882 40
$ printf 'Somebody set up us the bomb Main screen turn on\0' | dd bs=1 count=40 of
=/proc/4927/mem seek=140735402952841 conv=notrunc
40+0 records in
40+0 records out
40 bytes copied, 0.000229779 s, 174 kB/s
$ ps 4927
PID TTY STAT TIME COMMAND
4927 pts/4 S 0:00 Somebody set up us the bomb Main screen