📄 crt0.s
字号:
/* @(#)crt0.s 1.1 92/07/30 SMI *//* * "C" run-time program bootstrap. *//* * Copyright (c) 1987 Sun Microsystems, Inc. */#include <sys/syscall.h>#include <sys/mman.h>/* * Start a program by calling its "main" with argument list and environment * strings. In addition, if program requires dynamic link editing, obtain * and hand control off to the link editor to do so. */ .text .globl startstart: | Execution begins here lea 0,a6 | Initial stack frame link is 0 movl sp@,d2 | argc lea sp@(4),a3 | argv movl d2,d1 | Find end of argv[] as asll #2,d1 | sizeof(argv[0]) * argc lea a3@(4,d1:l),a4 | Yields environment movl a4,_environ | Save for program's use tstl __dp:l | Does this program require editing? beq 1f | No bsr __getrtld | getrtld()1: pea a4@ | main(argc, argv, envp) pea a3@ movl d2,sp@- jsr start_float | Initialize floating point__main: jsr _main | Do the program addw #12,sp | Clean up#ifdef OLD movl #0,sp- | Ignore main's return value#else movl d0,sp@- | Use main's return value#endif OLD jsr _exit | exit(status) addql #4,sp | In the event exit doesn't movl d0,sp@- | then _exit(exit(status)) jsr __exit /*NOTREACHED*//* * __getrtld: load and call the link editor. When a program is link edited * by "ld", a structure is created if the program is "incomplete". Such * programs must "complete themselves" by getting the link editor involved * again. *//* XXX Derive these constants */#define _RTLD_INTERFACE_ 1 /* Interface version */#define FRAME 0x38 /* sizeof (struct exec) + locals */#define A_MACH (-FRAME+0x0) /* Offsets into struct exec */#define A_MAGIC (-FRAME+0x2)#define A_TEXT (-FRAME+0x4)#define A_DATA (-FRAME+0x8)#define A_BSS (-FRAME+0xc)#define A_ENTRY (-FRAME+0x14)#define exec a6@(-FRAME) /* Symbols for stack offsets */#define a_mach a6@(A_MACH)#define a_magic a6@(A_MAGIC)#define a_text a6@(A_TEXT)#define a_data a6@(A_DATA)#define a_bss a6@(A_BSS)#define a_entry a6@(A_ENTRY)#define ldba a6@(-0x18) /* ld.so base address */#define fd_dz a6@(-0x14) /* fd on /dev/zero */#define fd_ld a6@(-0x10) /* fd on link editor */#define udp a6@(-0xc) /* &__DYNAMIC */#define ep a6@(-0x8) /* environ */#define break a6@(-0x4) /* &main */#define SEGSIZ 0x20000#define PAGSIZ 0x2000#define ZMAGIC 0413__getrtld: link a6,#-FRAME | Allocate frame moveml d2-d3,sp@- | Save some registers| Find and map in the link editor pea __e_ld | Find the link editor pea 0 | No flags pea __link_editor | File name jsr __open | fd_ld = open(link_editor, 0) addl #0x8,sp movl d0,fd_ld| Read in its a.out header pea 0x20 | Size of buffer pea exec | Address of buffer movl d0,sp@- | fd_ld jsr __read | count = read(fd_ld, &exec, sizeof) addl #0x10,sp | Clean cmpl #0x20,d0 | Get full count? jeq 1f | Yes2: lea __e_ld,a0 | Otherwise jra __errxit | dispatch error| Determine if we've got a reasonable executable1: cmpw #ZMAGIC,a_magic | Demand-paged executable? jne 2b | Nope, this is fatal| Determine how much of the address space the link editor will occupy movl #(PAGSIZ-1),d2 | Starts one page up addl a_text,d2 | Now figure out how long the text is andl #~(SEGSIZ-1),d2 | Figure out last text segment and addl #SEGSIZ,d2 | determine data segment start movl d2,d0 | d0 == amount for text + gap addl a_data,d0 | d0 == text + gap + data addl a_bss,d0 | d0 == text + gap + data + bss| Map in the link editor pea __e_mmap | Set up for mapping pea 0 | No offset movl fd_ld,sp@- | fd on link editor movl __mmap_assign,sp@- | Specify mapping options movl __mmap_ro,sp@- | Access protection movl d0,sp@- | How much we're mapping pea 0 | We don't care where it goes jsr __mmap | mmap(all of link editor) addl #0x18,sp | Clean up (but not error string) movl d0,ldba | Save the address| Now, map in the data segment in its proper position movl a_text,sp@- | Offset in file to data segment movl fd_ld,sp@- | fd on link editor movl __mmap_fixed,sp@- | Mapping options movl __mmap_prot,sp@- | Protection movl a_data,sp@- | Map in the whole data segment movl d2,d0 | Get relative start of data segment addl ldba,d0 | Calculate absolute address movl d0,sp@- jsr __mmap | mmap(abs, data segment) addl #0x18,sp | Clean up all but error string movl d0,d3 | Save address where data segment went| Unmap the gap between the text and data segments subl a_text,d2 | Calculate size of gap movl d2,sp@- | Use that as length of unmapping movl ldba,d0 | Set starting address as base + addl a_text,d0 | size of the text segment movl d0,sp@- jsr __munmap | Unmap the gap addl #0xc,sp | Clear arguments + error string| Obtain /dev/zero to build the bss from pea __e_zero | Set up for failure pea 0 | No flags pea __dev_zero | File name jsr __open | fd_dz = open(/dev/zero, 0) addql #0x8,sp | Pop non-error arguments movl d0,fd_dz | and save file descriptor| Map in enough to build bss from tstl a_bss | Any bss? jne 1f | No, skip all this addql #4,sp | Pop off error string jra 2f | and join common code1: pea 0 | Otherwise, map from offset 0 movl d0,sp@- | Using /dev/zero fd movl __mmap_fixed,sp@- | PRIVATE, FIXED movl __mmap_prot,sp@- | All access movl a_bss,sp@- | Use a bss's worth addl a_data,d3 | Starting at the end of the movl d3,sp@- | data segment jsr __mmap | mmap(/dev/zero, a_bss) addl #0x1c,sp | Clear all arguments| Fill in rest of argument list and call link editor2: lea __main,a0 | Pass movl a0,break | breakpoint address movl _environ,ep | Pass environment movl __dp,udp | and this program's __DYNAMIC pea ldba | Prepare to call link editor pea _RTLD_INTERFACE_ | Tell interface number movl ldba,a0 | Get link editor base address addl a_entry,a0 | Offset by entry point jsr a0@ | Call it addql #8,sp | Clean moveml sp@+,d2-d3 | Restore registers unlk a6 | and clean frame rts | and return| System call interfaces#define STDERR 2 /* File descriptor for errors */#define STATUS 0x7f /* Exit status */#define eo_open sp@(0xc) /* open() error pointer offset */#define eo_mmap sp@(0x1c) /* mmap() */#define eo_munmap sp@(0xc) /* munmap() */#define eo_read sp@(0x10) /* read */__open: movl eo_open,a0 | Get pointer to error structure pea SYS_open | Push trap code jra __syscom | Execute common code__mmap: movl eo_mmap,a0 | See above pea SYS_mmap jra __syscom__munmap: movl eo_munmap,a0 pea SYS_munmap jra __syscom__read: movl eo_read,a0 pea SYS_read__syscom: trap #0 | Do the system call bcss __errxit | Error? rts | No, return success__errxit: movl a0@+,sp@- | Push character count pea a0@ | and buffer address pea STDERR pea 0 | Dummy pea SYS_write trap #0 | write(stderr, &msg, count) movl #STATUS,sp@(4) pea SYS_exit trap #0 | _exit(status) /* NOTREACHED */| Initialized, read-only data .even__dp: .long __DYNAMIC | ld makes this 0 or a pointer__link_editor: | Name of file containing link editor .asciz "/usr/lib/ld.so"__dev_zero: | Name of source of zero'ed memory .asciz "/dev/zero" .even__e_ld: .long 0x18 | Missing/trashed link editor .ascii "crt0: no /usr/lib/ld.so\012" .even__e_mmap: | mmap/munmap don't work .long 0x25 .ascii "crt0: /usr/lib/ld.so mapping failure\012" .even__e_zero: | /dev/zero missing, unmappable .long 0x13 .ascii "crt0: no /dev/zero\012" .even__mmap_assign: | mmap flags for system assignment .long _MAP_NEW+MAP_PRIVATE__mmap_fixed: | mmap flags for program assignment .long _MAP_NEW+MAP_FIXED+MAP_PRIVATE__mmap_prot: | protection flags .long PROT_READ+PROT_WRITE+PROT_EXEC__mmap_ro: | read only .long PROT_READ+PROT_EXEC| Writeable data .data .globl _environ_environ: .long 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -