File indexing completed on 2023-09-15 22:40:41
b1abca8a5… Alex*0001
0002
0003
0004
c3193925d… Alex*0005
b1abca8a5… Alex*0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
360a3f914… Jona*0020
b1abca8a5… Alex*0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
df8c5a37e… Alex*0063 #ifdef __linux__
0064
b1abca8a5… Alex*0065 #include "config.h"
0066
df8c5a37e… Alex*0067 #include <stdarg.h>
b1abca8a5… Alex*0068 #include <stdio.h>
0069 #include <stdlib.h>
0070 #include <string.h>
0071 #include <sys/types.h>
28d7d5ba9… Alex*0072 #include <sys/stat.h>
b1abca8a5… Alex*0073 #include <fcntl.h>
e3001b6a7… Alex*0074 #include <sys/mman.h>
bfac60bfe… Alex*0075 #ifdef HAVE_SYS_SYSCALL_H
0076 # include <sys/syscall.h>
0077 #endif
28d7d5ba9… Alex*0078 #include <unistd.h>
b1abca8a5… Alex*0079 #ifdef HAVE_ELF_H
0080 # include <elf.h>
0081 #endif
0082 #ifdef HAVE_LINK_H
0083 # include <link.h>
0084 #endif
0085 #ifdef HAVE_SYS_LINK_H
0086 # include <sys/link.h>
0087 #endif
0088
d5a372abb… Alex*0089 #include "wine/asm.h"
df8c5a37e… Alex*0090 #include "main.h"
bd2d79524… Ken *0091
966233aee… Jino*0092 #pragma GCC visibility push(hidden)
0093
b1abca8a5… Alex*0094
0095 #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
0096 #define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
0097
0098 #define MAP_BASE_ADDR(l) 0
0099
0100 #ifndef MAP_COPY
0101 #define MAP_COPY MAP_PRIVATE
0102 #endif
0103 #ifndef MAP_NORESERVE
0104 #define MAP_NORESERVE 0
0105 #endif
0106
0107 static struct wine_preload_info preload_info[] =
0108 {
29922c227… Mart*0109 #if defined(__i386__) || defined(__arm__)
195ca1e85… Alex*0110 { (void *)0x00000000, 0x00010000 },
0111 { (void *)0x00010000, 0x00100000 },
4d35f3f27… Alex*0112 { (void *)0x00110000, 0x67ef0000 },
6b0836e3f… Tim *0113 { (void *)0x7f000000, 0x03000000 },
0a0862001… Alex*0114 #else
0115 { (void *)0x000000010000, 0x00100000 },
0116 { (void *)0x000000110000, 0x67ef0000 },
6b0836e3f… Tim *0117 { (void *)0x00007f000000, 0x00ff0000 },
0a0862001… Alex*0118 { (void *)0x7ffffe000000, 0x01ff0000 },
0119 #endif
e325efbd8… Alex*0120 { 0, 0 },
b1abca8a5… Alex*0121 { 0, 0 }
0122 };
0123
0124
0125 #undef DUMP_SEGMENTS
0126 #undef DUMP_AUX_INFO
0127 #undef DUMP_SYMS
1172754fc… Alex*0128 #undef DUMP_MAPS
b1abca8a5… Alex*0129
0130
0131 #ifndef PT_TLS
0132 #define PT_TLS 7
0133 #endif
0134
2113bd43f… Mike*0135 #ifndef AT_SYSINFO
0136 #define AT_SYSINFO 32
0137 #endif
0138 #ifndef AT_SYSINFO_EHDR
0139 #define AT_SYSINFO_EHDR 33
0140 #endif
0141
30a3866b7… Alex*0142 #ifndef DT_GNU_HASH
0143 #define DT_GNU_HASH 0x6ffffef5
0144 #endif
0145
fe031c937… Alex*0146 static size_t page_size, page_mask;
92425aab6… Alex*0147 static char *preloader_start, *preloader_end;
b1abca8a5… Alex*0148
0149 struct wld_link_map {
0150 ElfW(Addr) l_addr;
0151 ElfW(Dyn) *l_ld;
9f33a4b10… Alex*0152 ElfW(Phdr)*l_phdr;
b1abca8a5… Alex*0153 ElfW(Addr) l_entry;
0154 ElfW(Half) l_ldnum;
0155 ElfW(Half) l_phnum;
0156 ElfW(Addr) l_map_start, l_map_end;
0157 ElfW(Addr) l_interp;
0158 };
0159
3b8ab28c4… Alex*0160 struct wld_auxv
0161 {
0162 ElfW(Addr) a_type;
0163 union
0164 {
0165 ElfW(Addr) a_val;
0166 } a_un;
0167 };
b1abca8a5… Alex*0168
a31a75244… Aaro*0169
0170
0171
0172
0173
0174
0175
e66e227db… Eric*0176 void __bb_init_func(void) { return; }
a31a75244… Aaro*0177
0a0862001… Alex*0178 #ifdef __i386__
0179
a68d293ba… Alex*0180
0181
0182 static int thread_data[256];
0183
0184 struct
0185 {
0186
0187 unsigned int entry_number;
0188 unsigned long base_addr;
0189 unsigned int limit;
0190 unsigned int seg_32bit : 1;
0191 unsigned int contents : 2;
0192 unsigned int read_exec_only : 1;
0193 unsigned int limit_in_pages : 1;
0194 unsigned int seg_not_present : 1;
d8c41a25d… Fran*0195 unsigned int usable : 1;
a68d293ba… Alex*0196 unsigned int garbage : 25;
0197 } thread_ldt = { -1, (unsigned long)thread_data, 0xfffff, 1, 0, 0, 1, 0, 1, 0 };
0198
0199
b1abca8a5… Alex*0200
0201
0202
0203
9f33a4b10… Alex*0204
b1abca8a5… Alex*0205
fa6ffb4d5… Alex*0206 void _start(void);
b1abca8a5… Alex*0207 extern char _end[];
0208 __ASM_GLOBAL_FUNC(_start,
5f38bfed7… Keno*0209 __ASM_CFI("\t.cfi_undefined %eip\n")
a68d293ba… Alex*0210 "\tmovl $243,%eax\n"
0211 "\tmovl $thread_ldt,%ebx\n"
0212 "\tint $0x80\n"
0213 "\torl %eax,%eax\n"
0214 "\tjl 1f\n"
0215 "\tmovl thread_ldt,%eax\n"
0216 "\tshl $3,%eax\n"
0217 "\torl $3,%eax\n"
0218 "\tmov %ax,%gs\n"
0219 "\tmov %ax,%fs\n"
0220 "1:\tmovl %esp,%eax\n"
cc01e8ff0… Alex*0221 "\tleal -136(%esp),%esp\n"
9f33a4b10… Alex*0222 "\tpushl %eax\n"
0223 "\tpushl %esp\n"
b1abca8a5… Alex*0224 "\tcall wld_start\n"
9f33a4b10… Alex*0225 "\tpopl %ecx\n"
0226 "\tpopl %esp\n"
0227 "\tpush %eax\n"
b1abca8a5… Alex*0228 "\txor %eax,%eax\n"
0229 "\txor %ecx,%ecx\n"
0230 "\txor %edx,%edx\n"
4c4094e86… Alex*0231 "\tmov %ax,%gs\n"
b1abca8a5… Alex*0232 "\tret\n")
0233
bfac60bfe… Alex*0234
0235
0236 #define SYSCALL_RET(ret) (((ret) < 0 && (ret) > -4096) ? -1 : (ret))
0237
0238 static inline __attribute__((noreturn)) void wld_exit( int code )
0239 {
0240 for (;;)
e9f2eb524… Alex*0241 __asm__ __volatile__( "pushl %%ebx; movl %1,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0242 : : "a" (1 ), "r" (code) );
bfac60bfe… Alex*0243 }
0244
0245 static inline int wld_open( const char *name, int flags )
0246 {
0247 int ret;
e9f2eb524… Alex*0248 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0249 : "=a" (ret) : "0" (5 ), "r" (name), "c" (flags) );
bfac60bfe… Alex*0250 return SYSCALL_RET(ret);
0251 }
0252
0253 static inline int wld_close( int fd )
0254 {
0255 int ret;
e9f2eb524… Alex*0256 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0257 : "=a" (ret) : "0" (6 ), "r" (fd) );
bfac60bfe… Alex*0258 return SYSCALL_RET(ret);
0259 }
0260
0261 static inline ssize_t wld_read( int fd, void *buffer, size_t len )
0262 {
0263 int ret;
e9f2eb524… Alex*0264 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
0265 : "=a" (ret)
6f1932dbc… Alex*0266 : "0" (3 ), "r" (fd), "c" (buffer), "d" (len)
bfac60bfe… Alex*0267 : "memory" );
0268 return SYSCALL_RET(ret);
0269 }
0270
0271 static inline ssize_t wld_write( int fd, const void *buffer, size_t len )
0272 {
0273 int ret;
e9f2eb524… Alex*0274 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0275 : "=a" (ret) : "0" (4 ), "r" (fd), "c" (buffer), "d" (len) );
bfac60bfe… Alex*0276 return SYSCALL_RET(ret);
0277 }
0278
0279 static inline int wld_mprotect( const void *addr, size_t len, int prot )
0280 {
0281 int ret;
e9f2eb524… Alex*0282 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0283 : "=a" (ret) : "0" (125 ), "r" (addr), "c" (len), "d" (prot) );
bfac60bfe… Alex*0284 return SYSCALL_RET(ret);
0285 }
0286
45a632ee8… Alex*0287 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, unsigned int offset );
0288 __ASM_GLOBAL_FUNC(wld_mmap,
0289 "\tpushl %ebp\n"
0290 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
0291 "\tpushl %ebx\n"
0292 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
0293 "\tpushl %esi\n"
0294 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
0295 "\tpushl %edi\n"
0296 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
0297 "\tmovl $192,%eax\n"
0298 "\tmovl 20(%esp),%ebx\n"
0299 "\tmovl 24(%esp),%ecx\n"
0300 "\tmovl 28(%esp),%edx\n"
0301 "\tmovl 32(%esp),%esi\n"
0302 "\tmovl 36(%esp),%edi\n"
0303 "\tmovl 40(%esp),%ebp\n"
0304 "\tshrl $12,%ebp\n"
0305 "\tint $0x80\n"
0306 "\tcmpl $-4096,%eax\n"
9f06a197c… Alex*0307 "\tjbe 2f\n"
0308 "\tcmpl $-38,%eax\n"
0309 "\tjne 1f\n"
0310 "\tmovl $90,%eax\n"
0311 "\tleal 20(%esp),%ebx\n"
0312 "\tint $0x80\n"
0313 "\tcmpl $-4096,%eax\n"
0314 "\tjbe 2f\n"
0315 "1:\tmovl $-1,%eax\n"
0316 "2:\tpopl %edi\n"
45a632ee8… Alex*0317 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
0318 "\tpopl %esi\n"
0319 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
0320 "\tpopl %ebx\n"
0321 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
0322 "\tpopl %ebp\n"
0323 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
0324 "\tret\n" )
bfac60bfe… Alex*0325
fe031c937… Alex*0326 static inline int wld_prctl( int code, long arg )
c20d6c409… Alex*0327 {
0328 int ret;
0329 __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
6f1932dbc… Alex*0330 : "=a" (ret) : "0" (172 ), "r" (code), "c" (arg) );
c20d6c409… Alex*0331 return SYSCALL_RET(ret);
0332 }
0333
0a0862001… Alex*0334 #elif defined(__x86_64__)
0335
7e112c291… Alex*0336 void *thread_data[256];
0337
0a0862001… Alex*0338
0339
0340
0341
0342
0343
0344 void _start(void);
0345 extern char _end[];
0346 __ASM_GLOBAL_FUNC(_start,
5f38bfed7… Keno*0347 __ASM_CFI(".cfi_undefined %rip\n\t")
0a0862001… Alex*0348 "movq %rsp,%rax\n\t"
0349 "leaq -144(%rsp),%rsp\n\t"
7e112c291… Alex*0350 "movq %rax,(%rsp)\n\t"
81f7329f4… Jino*0351 "leaq thread_data(%rip),%rsi\n\t"
7e112c291… Alex*0352 "movq $0x1002,%rdi\n\t"
0353 "movq $158,%rax\n\t"
0354 "syscall\n\t"
0a0862001… Alex*0355 "movq %rsp,%rdi\n\t"
0356 "call wld_start\n\t"
0357 "movq (%rsp),%rsp\n\t"
0358 "pushq %rax\n\t"
0359 "xorq %rax,%rax\n\t"
0360 "xorq %rcx,%rcx\n\t"
0361 "xorq %rdx,%rdx\n\t"
0362 "xorq %rsi,%rsi\n\t"
0363 "xorq %rdi,%rdi\n\t"
0364 "xorq %r8,%r8\n\t"
0365 "xorq %r9,%r9\n\t"
0366 "xorq %r10,%r10\n\t"
0367 "xorq %r11,%r11\n\t"
0368 "ret")
0369
61d2d8079… Alex*0370 #define SYSCALL_FUNC( name, nr ) \
0371 __ASM_GLOBAL_FUNC( name, \
0372 "movq $" #nr ",%rax\n\t" \
0373 "movq %rcx,%r10\n\t" \
0374 "syscall\n\t" \
0375 "leaq 4096(%rax),%rcx\n\t" \
0376 "movq $-1,%rdx\n\t" \
0377 "cmp $4096,%rcx\n\t" \
0378 "cmovb %rdx,%rax\n\t" \
0379 "ret" )
0380
0381 #define SYSCALL_NOERR( name, nr ) \
0382 __ASM_GLOBAL_FUNC( name, \
0383 "movq $" #nr ",%rax\n\t" \
0384 "syscall\n\t" \
0385 "ret" )
0386
0387 void wld_exit( int code ) __attribute__((noreturn));
0388 SYSCALL_NOERR( wld_exit, 60 );
0389
0390 ssize_t wld_read( int fd, void *buffer, size_t len );
0391 SYSCALL_FUNC( wld_read, 0 );
0392
0393 ssize_t wld_write( int fd, const void *buffer, size_t len );
0394 SYSCALL_FUNC( wld_write, 1 );
0395
0396 int wld_open( const char *name, int flags );
0397 SYSCALL_FUNC( wld_open, 2 );
0398
0399 int wld_close( int fd );
0400 SYSCALL_FUNC( wld_close, 3 );
0a0862001… Alex*0401
0402 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
61d2d8079… Alex*0403 SYSCALL_FUNC( wld_mmap, 9 );
0a0862001… Alex*0404
61d2d8079… Alex*0405 int wld_mprotect( const void *addr, size_t len, int prot );
0406 SYSCALL_FUNC( wld_mprotect, 10 );
0a0862001… Alex*0407
33765285c… Qian*0408 int wld_prctl( int code, long arg );
61d2d8079… Alex*0409 SYSCALL_FUNC( wld_prctl, 157 );
0a0862001… Alex*0410
61d2d8079… Alex*0411 uid_t wld_getuid(void);
0412 SYSCALL_NOERR( wld_getuid, 102 );
0a0862001… Alex*0413
61d2d8079… Alex*0414 gid_t wld_getgid(void);
0415 SYSCALL_NOERR( wld_getgid, 104 );
0a0862001… Alex*0416
61d2d8079… Alex*0417 uid_t wld_geteuid(void);
0418 SYSCALL_NOERR( wld_geteuid, 107 );
0419
0420 gid_t wld_getegid(void);
0421 SYSCALL_NOERR( wld_getegid, 108 );
0a0862001… Alex*0422
27e92e550… Andr*0423 #elif defined(__aarch64__)
0424
c08e5560c… Andr*0425 void *thread_data[256];
0426
27e92e550… Andr*0427
0428
0429
0430
0431
0432
0433 void _start(void);
0434 extern char _end[];
0435 __ASM_GLOBAL_FUNC(_start,
0436 "mov x0, SP\n\t"
0437 "sub SP, SP, #144\n\t"
0438 "str x0, [SP]\n\t"
ac1761d1d… Alex*0439 "adrp x0, thread_data\n\t"
0440 "add x0, x0, :lo12:thread_data\n\t"
c08e5560c… Andr*0441 "msr tpidr_el0, x0\n\t"
27e92e550… Andr*0442 "mov x0, SP\n\t"
0443 "bl wld_start\n\t"
0444 "ldr x1, [SP]\n\t"
0445 "mov SP, x1\n\t"
0446 "mov x30, x0\n\t"
0447 "mov x0, #0\n\t"
0448 "mov x1, #0\n\t"
0449 "mov x2, #0\n\t"
0450 "mov x3, #0\n\t"
0451 "mov x4, #0\n\t"
0452 "mov x5, #0\n\t"
0453 "mov x6, #0\n\t"
0454 "mov x7, #0\n\t"
0455 "mov x8, #0\n\t"
0456 "mov x9, #0\n\t"
0457 "mov x10, #0\n\t"
0458 "mov x11, #0\n\t"
0459 "mov x12, #0\n\t"
0460 "mov x13, #0\n\t"
0461 "mov x14, #0\n\t"
0462 "mov x15, #0\n\t"
0463 "mov x16, #0\n\t"
0464 "mov x17, #0\n\t"
0465 "mov x18, #0\n\t"
0466 "ret")
0467
0468 #define SYSCALL_FUNC( name, nr ) \
0469 __ASM_GLOBAL_FUNC( name, \
0470 "stp x8, x9, [SP, #-16]!\n\t" \
0471 "mov x8, #" #nr "\n\t" \
0472 "svc #0\n\t" \
0473 "ldp x8, x9, [SP], #16\n\t" \
0474 "cmn x0, #1, lsl#12\n\t" \
0475 "cinv x0, x0, hi\n\t" \
0476 "b.hi 1f\n\t" \
0477 "ret\n\t" \
0478 "1: mov x0, #-1\n\t" \
0479 "ret" )
0480
0481 #define SYSCALL_NOERR( name, nr ) \
0482 __ASM_GLOBAL_FUNC( name, \
0483 "stp x8, x9, [SP, #-16]!\n\t" \
0484 "mov x8, #" #nr "\n\t" \
0485 "svc #0\n\t" \
0486 "ldp x8, x9, [SP], #16\n\t" \
0487 "ret" )
0488
0489 void wld_exit( int code ) __attribute__((noreturn));
0490 SYSCALL_NOERR( wld_exit, 93 );
0491
0492 ssize_t wld_read( int fd, void *buffer, size_t len );
0493 SYSCALL_FUNC( wld_read, 63 );
0494
0495 ssize_t wld_write( int fd, const void *buffer, size_t len );
0496 SYSCALL_FUNC( wld_write, 64 );
0497
0498 int wld_openat( int dirfd, const char *name, int flags );
0499 SYSCALL_FUNC( wld_openat, 56 );
0500
0501 int wld_open( const char *name, int flags )
0502 {
0503 return wld_openat(-100 , name, flags);
0504 }
0505
0506 int wld_close( int fd );
0507 SYSCALL_FUNC( wld_close, 57 );
0508
0509 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset );
0510 SYSCALL_FUNC( wld_mmap, 222 );
0511
0512 int wld_mprotect( const void *addr, size_t len, int prot );
0513 SYSCALL_FUNC( wld_mprotect, 226 );
0514
0515 int wld_prctl( int code, long arg );
0516 SYSCALL_FUNC( wld_prctl, 167 );
0517
0518 uid_t wld_getuid(void);
0519 SYSCALL_NOERR( wld_getuid, 174 );
0520
0521 gid_t wld_getgid(void);
0522 SYSCALL_NOERR( wld_getgid, 176 );
0523
0524 uid_t wld_geteuid(void);
0525 SYSCALL_NOERR( wld_geteuid, 175 );
0526
0527 gid_t wld_getegid(void);
0528 SYSCALL_NOERR( wld_getegid, 177 );
0529
29922c227… Mart*0530 #elif defined(__arm__)
0531
0532 void *thread_data[256];
0533
0534
0535
0536
0537
0538
0539
0540 void _start(void);
0541 extern char _end[];
0542 __ASM_GLOBAL_FUNC(_start,
f76097680… Mart*0543 __ASM_EHABI(".cantunwind\n\t")
29922c227… Mart*0544 "mov r0, sp\n\t"
0545 "sub sp, sp, #144\n\t"
0546 "str r0, [sp]\n\t"
0547 "ldr r0, =thread_data\n\t"
0548 "movw r7, #0x0005\n\t"
0549 "movt r7, #0xf\n\t"
0550 "svc #0\n\t"
0551 "mov r0, sp\n\t"
0552 "bl wld_start\n\t"
0553 "ldr r1, [sp]\n\t"
0554 "mov sp, r1\n\t"
0555 "mov lr, r0\n\t"
0556 "mov r0, #0\n\t"
0557 "mov r1, #0\n\t"
0558 "mov r2, #0\n\t"
0559 "mov r3, #0\n\t"
0560 "mov r12, #0\n\t"
0561 "bx lr\n\t"
0562 ".ltorg\n\t")
0563
0564 #define SYSCALL_FUNC( name, nr ) \
0565 __ASM_GLOBAL_FUNC( name, \
f76097680… Mart*0566 __ASM_EHABI(".cantunwind\n\t") \
29922c227… Mart*0567 "push {r4-r5,r7,lr}\n\t" \
0568 "ldr r4, [sp, #16]\n\t" \
0569 "ldr r5, [sp, #20]\n\t" \
0570 "mov r7, #" #nr "\n\t" \
0571 "svc #0\n\t" \
0572 "cmn r0, #4096\n\t" \
0573 "it hi\n\t" \
0574 "movhi r0, #-1\n\t" \
0575 "pop {r4-r5,r7,pc}\n\t" )
0576
0577 #define SYSCALL_NOERR( name, nr ) \
0578 __ASM_GLOBAL_FUNC( name, \
f76097680… Mart*0579 __ASM_EHABI(".cantunwind\n\t") \
29922c227… Mart*0580 "push {r7,lr}\n\t" \
0581 "mov r7, #" #nr "\n\t" \
0582 "svc #0\n\t" \
0583 "pop {r7,pc}\n\t" )
0584
0585 void wld_exit( int code ) __attribute__((noreturn));
0586 SYSCALL_NOERR( wld_exit, 1 );
0587
0588 ssize_t wld_read( int fd, void *buffer, size_t len );
0589 SYSCALL_FUNC( wld_read, 3 );
0590
0591 ssize_t wld_write( int fd, const void *buffer, size_t len );
0592 SYSCALL_FUNC( wld_write, 4 );
0593
0594 int wld_openat( int dirfd, const char *name, int flags );
0595 SYSCALL_FUNC( wld_openat, 322 );
0596
0597 int wld_open( const char *name, int flags )
0598 {
0599 return wld_openat(-100 , name, flags);
0600 }
0601
0602 int wld_close( int fd );
0603 SYSCALL_FUNC( wld_close, 6 );
0604
0605 void *wld_mmap2( void *start, size_t len, int prot, int flags, int fd, int offset );
0606 SYSCALL_FUNC( wld_mmap2, 192 );
0607
0608 void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset )
0609 {
0610 return wld_mmap2(start, len, prot, flags, fd, offset >> 12);
0611 }
0612
0613 int wld_mprotect( const void *addr, size_t len, int prot );
0614 SYSCALL_FUNC( wld_mprotect, 125 );
0615
0616 int wld_prctl( int code, long arg );
0617 SYSCALL_FUNC( wld_prctl, 172 );
0618
0619 uid_t wld_getuid(void);
0620 SYSCALL_NOERR( wld_getuid, 24 );
0621
0622 gid_t wld_getgid(void);
0623 SYSCALL_NOERR( wld_getgid, 47 );
0624
0625 uid_t wld_geteuid(void);
0626 SYSCALL_NOERR( wld_geteuid, 49 );
0627
0628 gid_t wld_getegid(void);
0629 SYSCALL_NOERR( wld_getegid, 50 );
0630
0631 unsigned long long __aeabi_uidivmod(unsigned int num, unsigned int den)
0632 {
0633 unsigned int bit = 1;
0634 unsigned int quota = 0;
0635 if (!den)
0636 wld_exit(1);
0637 while (den < num && !(den & 0x80000000)) {
0638 den <<= 1;
0639 bit <<= 1;
0640 }
0641 do {
0642 if (den <= num) {
0643 quota |= bit;
0644 num -= den;
0645 }
0646 bit >>= 1;
0647 den >>= 1;
0648 } while (bit);
0649 return ((unsigned long long)num << 32) | quota;
0650 }
0651
0a0862001… Alex*0652 #else
0653 #error preloader not implemented for this CPU
0654 #endif
bfac60bfe… Alex*0655
df8c5a37e… Alex*0656
0657
0658 static int wld_strcmp( const char *str1, const char *str2 )
0659 {
0660 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
0661 return *str1 - *str2;
0662 }
0663
0664 static int wld_strncmp( const char *str1, const char *str2, size_t len )
0665 {
0666 if (len <= 0) return 0;
0667 while ((--len > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
0668 return *str1 - *str2;
0669 }
0670
0671 static inline void *wld_memset( void *dest, int val, size_t len )
0672 {
0673 char *dst = dest;
0674 while (len--) *dst++ = val;
0675 return dest;
0676 }
0677
0678
0679
0680
0681
0682
0683
0684
0685 static int wld_vsprintf(char *buffer, const char *fmt, va_list args )
0686 {
0687 static const char hex_chars[16] = "0123456789abcdef";
0688 const char *p = fmt;
0689 char *str = buffer;
0690 int i;
0691
0692 while( *p )
0693 {
0694 if( *p == '%' )
0695 {
0696 p++;
0697 if( *p == 'x' )
0698 {
0699 unsigned int x = va_arg( args, unsigned int );
0700 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0701 *str++ = hex_chars[(x>>(i*4))&0xf];
0702 }
0703 else if (p[0] == 'l' && p[1] == 'x')
0704 {
0705 unsigned long x = va_arg( args, unsigned long );
0706 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0707 *str++ = hex_chars[(x>>(i*4))&0xf];
0708 p++;
0709 }
0710 else if( *p == 'p' )
0711 {
0712 unsigned long x = (unsigned long)va_arg( args, void * );
0713 for (i = 2*sizeof(x) - 1; i >= 0; i--)
0714 *str++ = hex_chars[(x>>(i*4))&0xf];
0715 }
0716 else if( *p == 's' )
0717 {
0718 char *s = va_arg( args, char * );
0719 while(*s)
0720 *str++ = *s++;
0721 }
0722 else if( *p == 0 )
0723 break;
0724 p++;
0725 }
0726 *str++ = *p++;
0727 }
0728 *str = 0;
0729 return str - buffer;
0730 }
0731
0732 static __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... )
0733 {
0734 va_list args;
0735 char buffer[256];
0736 int len;
0737
0738 va_start( args, fmt );
0739 len = wld_vsprintf(buffer, fmt, args );
0740 va_end( args );
0741 wld_write(2, buffer, len);
0742 }
0743
0744 static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... )
0745 {
0746 va_list args;
0747 char buffer[256];
0748 int len;
0749
0750 va_start( args, fmt );
0751 len = wld_vsprintf(buffer, fmt, args );
0752 va_end( args );
0753 wld_write(2, buffer, len);
0754 wld_exit(1);
0755 }
0756
da74da293… Jino*0757
0758
0759
0760
0761
0762
0763 unsigned long __stack_chk_guard = 0;
0764
0765 void __attribute__((noreturn)) __stack_chk_fail(void)
0766 {
0767 static const char message[] = "preloader: stack overrun detected, crashing\n";
0768
0769
0770 wld_write(2, message, sizeof(message) - 1);
0771
0772
0773 *(volatile char *)0;
0774
0775
0776 wld_exit(1);
0777 }
0778
0779 void __attribute__((noreturn)) __stack_chk_fail_local(void)
0780 {
0781 __stack_chk_fail();
0782 }
0783
b1abca8a5… Alex*0784 #ifdef DUMP_AUX_INFO
0785
0786
0787
0788
3b8ab28c4… Alex*0789 static void dump_auxiliary( struct wld_auxv *av )
b1abca8a5… Alex*0790 {
9f33a4b10… Alex*0791 #define NAME(at) { at, #at }
0792 static const struct { int val; const char *name; } names[] =
0793 {
0794 NAME(AT_BASE),
0795 NAME(AT_CLKTCK),
0796 NAME(AT_EGID),
0797 NAME(AT_ENTRY),
0798 NAME(AT_EUID),
0799 NAME(AT_FLAGS),
0800 NAME(AT_GID),
0801 NAME(AT_HWCAP),
0802 NAME(AT_PAGESZ),
0803 NAME(AT_PHDR),
0804 NAME(AT_PHENT),
0805 NAME(AT_PHNUM),
0806 NAME(AT_PLATFORM),
f558741fa… Alex*0807 NAME(AT_SYSINFO),
0808 NAME(AT_SYSINFO_EHDR),
9f33a4b10… Alex*0809 NAME(AT_UID),
0810 { 0, NULL }
0811 };
0812 #undef NAME
0813
0814 int i;
0815
0816 for ( ; av->a_type != AT_NULL; av++)
0817 {
0818 for (i = 0; names[i].name; i++) if (names[i].val == av->a_type) break;
fe031c937… Alex*0819 if (names[i].name) wld_printf("%s = %lx\n", names[i].name, (unsigned long)av->a_un.a_val);
0820 else wld_printf( "%lx = %lx\n", (unsigned long)av->a_type, (unsigned long)av->a_un.a_val );
9f33a4b10… Alex*0821 }
b1abca8a5… Alex*0822 }
0823 #endif
0824
0825
9f33a4b10… Alex*0826
b1abca8a5… Alex*0827
9f33a4b10… Alex*0828
b1abca8a5… Alex*0829
3b8ab28c4… Alex*0830 static void set_auxiliary_values( struct wld_auxv *av, const struct wld_auxv *new_av,
0831 const struct wld_auxv *delete_av, void **stack )
b1abca8a5… Alex*0832 {
f558741fa… Alex*0833 int i, j, av_count = 0, new_count = 0, delete_count = 0;
0834 char *src, *dst;
9f33a4b10… Alex*0835
0836
0837 while (av[av_count].a_type != AT_NULL) av_count++;
0838
f558741fa… Alex*0839
0840 for (j = 0; delete_av[j].a_type != AT_NULL; j++)
0841 {
0842 for (i = 0; i < av_count; i++) if (av[i].a_type == delete_av[j].a_type)
0843 {
0844 av[i].a_type = av[av_count-1].a_type;
0845 av[i].a_un.a_val = av[av_count-1].a_un.a_val;
0846 av[--av_count].a_type = AT_NULL;
0847 delete_count++;
0848 break;
0849 }
0850 }
0851
9f33a4b10… Alex*0852
0853 for (j = 0; new_av[j].a_type != AT_NULL; j++)
6d2099f4f… Alex*0854 {
9f33a4b10… Alex*0855 for (i = 0; i < av_count; i++) if (av[i].a_type == new_av[j].a_type) break;
0856 if (i == av_count) new_count++;
6d2099f4f… Alex*0857 }
9f33a4b10… Alex*0858
f558741fa… Alex*0859 src = (char *)*stack;
0860 dst = src - (new_count - delete_count) * sizeof(*av);
144cb78db… Alex*0861 dst = (char *)((unsigned long)dst & ~15);
0862 if (dst < src)
f558741fa… Alex*0863 {
0864 int len = (char *)(av + av_count + 1) - src;
0865 for (i = 0; i < len; i++) dst[i] = src[i];
0866 }
144cb78db… Alex*0867 else if (dst > src)
9f33a4b10… Alex*0868 {
2bea45dd0… Hara*0869 int len = (char *)(av + av_count + 1) - src;
f558741fa… Alex*0870 for (i = len - 1; i >= 0; i--) dst[i] = src[i];
9f33a4b10… Alex*0871 }
f558741fa… Alex*0872 *stack = dst;
3b8ab28c4… Alex*0873 av = (struct wld_auxv *)((char *)av + (dst - src));
9f33a4b10… Alex*0874
0875
0876 for (j = 0; new_av[j].a_type != AT_NULL; j++)
0877 {
0878 for (i = 0; i < av_count; i++) if (av[i].a_type == new_av[j].a_type) break;
0879 if (i < av_count) av[i].a_un.a_val = new_av[j].a_un.a_val;
0880 else
0881 {
0882 av[av_count].a_type = new_av[j].a_type;
0883 av[av_count].a_un.a_val = new_av[j].a_un.a_val;
0884 av_count++;
0885 }
0886 }
0887
0888 #ifdef DUMP_AUX_INFO
0889 wld_printf("New auxiliary info:\n");
0890 dump_auxiliary( av );
0891 #endif
b1abca8a5… Alex*0892 }
0893
0894
0895
0896
0897
0898
38dfa2f45… Jino*0899 static ElfW(Addr) get_auxiliary( struct wld_auxv *av, int type, ElfW(Addr) def_val )
b1abca8a5… Alex*0900 {
0901 for ( ; av->a_type != AT_NULL; av++)
9f33a4b10… Alex*0902 if( av->a_type == type ) return av->a_un.a_val;
0903 return def_val;
b1abca8a5… Alex*0904 }
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914 static void map_so_lib( const char *name, struct wld_link_map *l)
0915 {
0916 int fd;
0917 unsigned char buf[0x800];
0918 ElfW(Ehdr) *header = (ElfW(Ehdr)*)buf;
0919 ElfW(Phdr) *phdr, *ph;
0920
0921 struct loadcmd
0922 {
0923 ElfW(Addr) mapstart, mapend, dataend, allocend;
0924 off_t mapoff;
0925 int prot;
0926 } loadcmds[16], *c;
0927 size_t nloadcmds = 0, maplength;
0928
bfac60bfe… Alex*0929 fd = wld_open( name, O_RDONLY );
b1abca8a5… Alex*0930 if (fd == -1) fatal_error("%s: could not open\n", name );
0931
bfac60bfe… Alex*0932 if (wld_read( fd, buf, sizeof(buf) ) != sizeof(buf))
b1abca8a5… Alex*0933 fatal_error("%s: failed to read ELF header\n", name);
0934
0935 phdr = (void*) (((unsigned char*)buf) + header->e_phoff);
0936
0937 if( ( header->e_ident[0] != 0x7f ) ||
0938 ( header->e_ident[1] != 'E' ) ||
0939 ( header->e_ident[2] != 'L' ) ||
0940 ( header->e_ident[3] != 'F' ) )
0941 fatal_error( "%s: not an ELF binary... don't know how to load it\n", name );
0942
0a0862001… Alex*0943 #ifdef __i386__
b1abca8a5… Alex*0944 if( header->e_machine != EM_386 )
0945 fatal_error("%s: not an i386 ELF binary... don't know how to load it\n", name );
0a0862001… Alex*0946 #elif defined(__x86_64__)
0947 if( header->e_machine != EM_X86_64 )
0948 fatal_error("%s: not an x86-64 ELF binary... don't know how to load it\n", name );
27e92e550… Andr*0949 #elif defined(__aarch64__)
0950 if( header->e_machine != EM_AARCH64 )
039d267b0… Aust*0951 fatal_error("%s: not an aarch64 ELF binary... don't know how to load it\n", name );
29922c227… Mart*0952 #elif defined(__arm__)
0953 if( header->e_machine != EM_ARM )
0954 fatal_error("%s: not an arm ELF binary... don't know how to load it\n", name );
0a0862001… Alex*0955 #endif
b1abca8a5… Alex*0956
0957 if (header->e_phnum > sizeof(loadcmds)/sizeof(loadcmds[0]))
0958 fatal_error( "%s: oops... not enough space for load commands\n", name );
0959
0960 maplength = header->e_phnum * sizeof (ElfW(Phdr));
0961 if (header->e_phoff + maplength > sizeof(buf))
0962 fatal_error( "%s: oops... not enough space for ELF headers\n", name );
0963
0964 l->l_ld = 0;
0965 l->l_addr = 0;
0966 l->l_phdr = 0;
0967 l->l_phnum = header->e_phnum;
0968 l->l_entry = header->e_entry;
0969 l->l_interp = 0;
0970
0971 for (ph = phdr; ph < &phdr[l->l_phnum]; ++ph)
0972 {
0973
0974 #ifdef DUMP_SEGMENTS
092ac1fbf… Alex*0975 wld_printf( "ph = %p\n", ph );
fe031c937… Alex*0976 wld_printf( " p_type = %lx\n", (unsigned long)ph->p_type );
0977 wld_printf( " p_flags = %lx\n", (unsigned long)ph->p_flags );
0978 wld_printf( " p_offset = %lx\n", (unsigned long)ph->p_offset );
0979 wld_printf( " p_vaddr = %lx\n", (unsigned long)ph->p_vaddr );
0980 wld_printf( " p_paddr = %lx\n", (unsigned long)ph->p_paddr );
0981 wld_printf( " p_filesz = %lx\n", (unsigned long)ph->p_filesz );
0982 wld_printf( " p_memsz = %lx\n", (unsigned long)ph->p_memsz );
0983 wld_printf( " p_align = %lx\n", (unsigned long)ph->p_align );
b1abca8a5… Alex*0984 #endif
0985
0986 switch (ph->p_type)
0987 {
0988
0989
0990
0991 case PT_DYNAMIC:
0992 l->l_ld = (void *) ph->p_vaddr;
0993 l->l_ldnum = ph->p_memsz / sizeof (Elf32_Dyn);
0994 break;
0995
0996 case PT_PHDR:
0997 l->l_phdr = (void *) ph->p_vaddr;
0998 break;
0999
1000 case PT_LOAD:
1001 {
1002 if ((ph->p_align & page_mask) != 0)
1003 fatal_error( "%s: ELF load command alignment not page-aligned\n", name );
1004
1005 if (((ph->p_vaddr - ph->p_offset) & (ph->p_align - 1)) != 0)
1006 fatal_error( "%s: ELF load command address/offset not properly aligned\n", name );
1007
1008 c = &loadcmds[nloadcmds++];
1009 c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
1010 c->mapend = ((ph->p_vaddr + ph->p_filesz + page_mask) & ~page_mask);
1011 c->dataend = ph->p_vaddr + ph->p_filesz;
1012 c->allocend = ph->p_vaddr + ph->p_memsz;
1013 c->mapoff = ph->p_offset & ~(ph->p_align - 1);
1014
1015 c->prot = 0;
1016 if (ph->p_flags & PF_R)
1017 c->prot |= PROT_READ;
1018 if (ph->p_flags & PF_W)
1019 c->prot |= PROT_WRITE;
1020 if (ph->p_flags & PF_X)
1021 c->prot |= PROT_EXEC;
1022 }
1023 break;
1024
1025 case PT_INTERP:
1026 l->l_interp = ph->p_vaddr;
1027 break;
1028
1029 case PT_TLS:
1030
1031
1032
1033
1034
1035 case PT_SHLIB:
1036 case PT_NOTE:
1037 default:
1038 break;
1039 }
1040 }
1041
1042
7b544af17… Eric*1043 if (!nloadcmds)
1044 fatal_error( "%s: no segments to load\n", name );
b1abca8a5… Alex*1045 c = loadcmds;
1046
1047
1048 maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart;
1049
1050 if( header->e_type == ET_DYN )
1051 {
1052 ElfW(Addr) mappref;
1053 mappref = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart)
1054 - MAP_BASE_ADDR (l));
1055
1056
bfac60bfe… Alex*1057 l->l_map_start = (ElfW(Addr)) wld_mmap ((void *) mappref, maplength,
b1abca8a5… Alex*1058 c->prot, MAP_COPY | MAP_FILE,
1059 fd, c->mapoff);
1060
1061
1062
1063 l->l_map_end = l->l_map_start + maplength;
1064 l->l_addr = l->l_map_start - c->mapstart;
1065
bfac60bfe… Alex*1066 wld_mprotect ((caddr_t) (l->l_addr + c->mapend),
b1abca8a5… Alex*1067 loadcmds[nloadcmds - 1].allocend - c->mapend,
1068 PROT_NONE);
1069 goto postmap;
1070 }
1071 else
1072 {
1073
1074 if ((char *)c->mapstart + maplength > preloader_start &&
1075 (char *)c->mapstart <= preloader_end)
092ac1fbf… Alex*1076 fatal_error( "%s: binary overlaps preloader (%p-%p)\n",
1077 name, (char *)c->mapstart, (char *)c->mapstart + maplength );
b1abca8a5… Alex*1078
1079 ELF_FIXED_ADDRESS (loader, c->mapstart);
1080 }
1081
1082
1083 l->l_map_start = c->mapstart + l->l_addr;
1084 l->l_map_end = l->l_map_start + maplength;
1085
1086 while (c < &loadcmds[nloadcmds])
1087 {
1088 if (c->mapend > c->mapstart)
1089
bfac60bfe… Alex*1090 wld_mmap ((void *) (l->l_addr + c->mapstart),
b1abca8a5… Alex*1091 c->mapend - c->mapstart, c->prot,
1092 MAP_FIXED | MAP_COPY | MAP_FILE, fd, c->mapoff);
1093
1094 postmap:
1095 if (l->l_phdr == 0
1096 && (ElfW(Off)) c->mapoff <= header->e_phoff
1097 && ((size_t) (c->mapend - c->mapstart + c->mapoff)
1098 >= header->e_phoff + header->e_phnum * sizeof (ElfW(Phdr))))
1099
fe031c937… Alex*1100 l->l_phdr = (void *)(unsigned long)(c->mapstart + header->e_phoff - c->mapoff);
b1abca8a5… Alex*1101
1102 if (c->allocend > c->dataend)
1103 {
1104
1105
1106 ElfW(Addr) zero, zeroend, zeropage;
1107
1108 zero = l->l_addr + c->dataend;
1109 zeroend = l->l_addr + c->allocend;
1110 zeropage = (zero + page_mask) & ~page_mask;
1111
1112
1113
1114
1115
1116 zeroend = (zeroend + page_mask) & ~page_mask;
1117
1118 if (zeroend < zeropage)
1119 {
1120
1121
1122 zeropage = zeroend;
1123 }
1124
1125 if (zeropage > zero)
1126 {
1127
1128 if ((c->prot & PROT_WRITE) == 0)
1129 {
1130
bfac60bfe… Alex*1131 wld_mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot|PROT_WRITE);
b1abca8a5… Alex*1132 }
bfac60bfe… Alex*1133 wld_memset ((void *) zero, '\0', zeropage - zero);
b1abca8a5… Alex*1134 if ((c->prot & PROT_WRITE) == 0)
bfac60bfe… Alex*1135 wld_mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot);
b1abca8a5… Alex*1136 }
1137
1138 if (zeroend > zeropage)
1139 {
1140
df9fda760… Aust*1141 wld_mmap ((caddr_t) zeropage, zeroend - zeropage,
b1abca8a5… Alex*1142 c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
1143 -1, 0);
1144 }
1145 }
1146
1147 ++c;
1148 }
1149
1150 if (l->l_phdr == NULL) fatal_error("no program header\n");
1151
1152 l->l_phdr = (void *)((ElfW(Addr))l->l_phdr + l->l_addr);
1153 l->l_entry += l->l_addr;
1154
bfac60bfe… Alex*1155 wld_close( fd );
b1abca8a5… Alex*1156 }
1157
1158
097867deb… Alex*1159 static unsigned int wld_elf_hash( const char *name )
8aab67d23… Alex*1160 {
1161 unsigned int hi, hash = 0;
1162 while (*name)
1163 {
1164 hash = (hash << 4) + (unsigned char)*name++;
1165 hi = hash & 0xf0000000;
1166 hash ^= hi;
1167 hash ^= hi >> 24;
1168 }
1169 return hash;
1170 }
1171
30a3866b7… Alex*1172 static unsigned int gnu_hash( const char *name )
1173 {
1174 unsigned int h = 5381;
1175 while (*name) h = h * 33 + (unsigned char)*name++;
1176 return h;
1177 }
1178
b1abca8a5… Alex*1179
1180
1181
60fb3d4b6… Alex*1182 static void *find_symbol( const struct wld_link_map *map, const char *var, int type )
b1abca8a5… Alex*1183 {
1184 const ElfW(Dyn) *dyn = NULL;
1185 const ElfW(Phdr) *ph;
1186 const ElfW(Sym) *symtab = NULL;
1ecfff38b… Alex*1187 const Elf32_Word *hashtab = NULL;
30a3866b7… Alex*1188 const Elf32_Word *gnu_hashtab = NULL;
b1abca8a5… Alex*1189 const char *strings = NULL;
1ecfff38b… Alex*1190 Elf32_Word idx;
b1abca8a5… Alex*1191
1192
1193 #ifdef DUMP_SYMS
60fb3d4b6… Alex*1194 wld_printf("%p %x\n", map->l_phdr, map->l_phnum );
b1abca8a5… Alex*1195 #endif
1196
60fb3d4b6… Alex*1197 for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
b1abca8a5… Alex*1198 {
1199 if( PT_DYNAMIC == ph->p_type )
1200 {
60fb3d4b6… Alex*1201 dyn = (void *)(ph->p_vaddr + map->l_addr);
b1abca8a5… Alex*1202 break;
1203 }
1204 }
1205 if( !dyn ) return NULL;
1206
1207 while( dyn->d_tag )
1208 {
1209 if( dyn->d_tag == DT_STRTAB )
60fb3d4b6… Alex*1210 strings = (const char*)(dyn->d_un.d_ptr + map->l_addr);
b1abca8a5… Alex*1211 if( dyn->d_tag == DT_SYMTAB )
60fb3d4b6… Alex*1212 symtab = (const ElfW(Sym) *)(dyn->d_un.d_ptr + map->l_addr);
b1abca8a5… Alex*1213 if( dyn->d_tag == DT_HASH )
60fb3d4b6… Alex*1214 hashtab = (const Elf32_Word *)(dyn->d_un.d_ptr + map->l_addr);
30a3866b7… Alex*1215 if( dyn->d_tag == DT_GNU_HASH )
60fb3d4b6… Alex*1216 gnu_hashtab = (const Elf32_Word *)(dyn->d_un.d_ptr + map->l_addr);
b1abca8a5… Alex*1217 #ifdef DUMP_SYMS
fe031c937… Alex*1218 wld_printf("%lx %p\n", (unsigned long)dyn->d_tag, (void *)dyn->d_un.d_ptr );
b1abca8a5… Alex*1219 #endif
1220 dyn++;
1221 }
1222
1223 if( (!symtab) || (!strings) ) return NULL;
1224
30a3866b7… Alex*1225 if (gnu_hashtab)
1226 {
1227 const unsigned int hash = gnu_hash(var);
1228 const Elf32_Word nbuckets = gnu_hashtab[0];
1229 const Elf32_Word symbias = gnu_hashtab[1];
1230 const Elf32_Word nwords = gnu_hashtab[2];
1231 const ElfW(Addr) *bitmask = (const ElfW(Addr) *)(gnu_hashtab + 4);
1232 const Elf32_Word *buckets = (const Elf32_Word *)(bitmask + nwords);
1233 const Elf32_Word *chains = buckets + nbuckets - symbias;
1234
1235 if (!(idx = buckets[hash % nbuckets])) return NULL;
1236 do
1237 {
1238 if ((chains[idx] & ~1u) == (hash & ~1u) &&
8b4ed00b5… Alex*1239 ELF32_ST_BIND(symtab[idx].st_info) == STB_GLOBAL &&
1240 ELF32_ST_TYPE(symtab[idx].st_info) == type &&
30a3866b7… Alex*1241 !wld_strcmp( strings + symtab[idx].st_name, var ))
1242 goto found;
1243 } while (!(chains[idx++] & 1u));
1244 }
1245 else if (hashtab)
b1abca8a5… Alex*1246 {
097867deb… Alex*1247 const unsigned int hash = wld_elf_hash(var);
1ecfff38b… Alex*1248 const Elf32_Word nbuckets = hashtab[0];
1249 const Elf32_Word *buckets = hashtab + 2;
1250 const Elf32_Word *chains = buckets + nbuckets;
8aab67d23… Alex*1251
8b4ed00b5… Alex*1252 for (idx = buckets[hash % nbuckets]; idx; idx = chains[idx])
b1abca8a5… Alex*1253 {
8b4ed00b5… Alex*1254 if (ELF32_ST_BIND(symtab[idx].st_info) == STB_GLOBAL &&
1255 ELF32_ST_TYPE(symtab[idx].st_info) == type &&
8aab67d23… Alex*1256 !wld_strcmp( strings + symtab[idx].st_name, var ))
30a3866b7… Alex*1257 goto found;
b1abca8a5… Alex*1258 }
1259 }
1260 return NULL;
30a3866b7… Alex*1261
1262 found:
1263 #ifdef DUMP_SYMS
fe031c937… Alex*1264 wld_printf("Found %s -> %p\n", strings + symtab[idx].st_name, (void *)symtab[idx].st_value );
30a3866b7… Alex*1265 #endif
60fb3d4b6… Alex*1266 return (void *)(symtab[idx].st_value + map->l_addr);
b1abca8a5… Alex*1267 }
1268
df8c5a37e… Alex*1269
1270
1271
1272
1273
1274 static void preload_reserve( const char *str )
1275 {
1276 const char *p;
1277 unsigned long result = 0;
1278 void *start = NULL, *end = NULL;
1279 int i, first = 1;
1280
1281 for (p = str; *p; p++)
1282 {
1283 if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
1284 else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
1285 else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
1286 else if (*p == '-')
1287 {
1288 if (!first) goto error;
1289 start = (void *)(result & ~page_mask);
1290 result = 0;
1291 first = 0;
1292 }
1293 else goto error;
1294 }
1295 if (!first) end = (void *)((result + page_mask) & ~page_mask);
1296 else if (result) goto error;
1297
1298
1299 if (end <= start) start = end = NULL;
1300 else if ((char *)end > preloader_start &&
1301 (char *)start <= preloader_end)
1302 {
1303 wld_printf( "WINEPRELOADRESERVE range %p-%p overlaps preloader %p-%p\n",
1304 start, end, preloader_start, preloader_end );
1305 start = end = NULL;
1306 }
1307
1308
1309 for (i = 0; preload_info[i].size; i++)
1310 {
1311 if ((char *)preload_info[i].addr > (char *)0x00110000) break;
1312 if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
1313 {
1314 start = end = NULL;
1315 break;
1316 }
1317 if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
1318 start = (char *)preload_info[i].addr + preload_info[i].size;
1319 }
1320
1321 while (preload_info[i].size) i++;
1322 preload_info[i].addr = start;
1323 preload_info[i].size = (char *)end - (char *)start;
1324 return;
1325
1326 error:
1327 fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
1328 }
1329
13029a253… Alex*1330
1331 static int is_addr_reserved( const void *addr )
1332 {
1333 int i;
1334
1335 for (i = 0; preload_info[i].size; i++)
1336 {
1337 if ((const char *)addr >= (const char *)preload_info[i].addr &&
1338 (const char *)addr < (const char *)preload_info[i].addr + preload_info[i].size)
1339 return 1;
1340 }
1341 return 0;
1342 }
1343
df8c5a37e… Alex*1344
1345 static void remove_preload_range( int i )
1346 {
1347 while (preload_info[i].size)
1348 {
1349 preload_info[i].addr = preload_info[i+1].addr;
1350 preload_info[i].size = preload_info[i+1].size;
1351 i++;
1352 }
1353 }
1354
f558741fa… Alex*1355
1356
1357
1358
1359
3b8ab28c4… Alex*1360 static int is_in_preload_range( const struct wld_auxv *av, int type )
f558741fa… Alex*1361 {
13029a253… Alex*1362 while (av->a_type != AT_NULL)
f558741fa… Alex*1363 {
13029a253… Alex*1364 if (av->a_type == type) return is_addr_reserved( (const void *)av->a_un.a_val );
1365 av++;
f558741fa… Alex*1366 }
1367 return 0;
1368 }
92425aab6… Alex*1369
c20d6c409… Alex*1370
1371 static void set_process_name( int argc, char *argv[] )
1372 {
e1e54d1ee… Jori*1373 int i;
1374 unsigned int off;
c20d6c409… Alex*1375 char *p, *name, *end;
1376
1377
1378 for (p = name = argv[1]; *p; p++) if (p[0] == '/' && p[1]) name = p + 1;
fe031c937… Alex*1379 if (wld_prctl( 15 , (long)name ) == -1) return;
c20d6c409… Alex*1380
1381
1382 end = argv[argc - 1];
1383 while (*end) end++;
1384 off = argv[1] - argv[0];
1385 for (p = argv[1]; p <= end; p++) *(p - off) = *p;
1386 wld_memset( end - off, 0, off );
1387 for (i = 1; i < argc; i++) argv[i] -= off;
1388 }
1389
1390
b1abca8a5… Alex*1391
1392
1393
1394
1395
1396
1397
9f33a4b10… Alex*1398 void* wld_start( void **stack )
b1abca8a5… Alex*1399 {
fe031c937… Alex*1400 long i, *pargc;
b1abca8a5… Alex*1401 char **argv, **p;
92425aab6… Alex*1402 char *interp, *reserve = NULL;
a2d76cb43… Alex*1403 struct wld_auxv new_av[8], delete_av[3], *av;
b1abca8a5… Alex*1404 struct wld_link_map main_binary_map, ld_so_map;
1405 struct wine_preload_info **wine_main_preload_info;
1406
9f33a4b10… Alex*1407 pargc = *stack;
1408 argv = (char **)pargc + 1;
c3193925d… Alex*1409 if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] );
b1abca8a5… Alex*1410
1411
9f33a4b10… Alex*1412 p = argv + *pargc + 1;
b1abca8a5… Alex*1413
1414
92425aab6… Alex*1415 while (*p)
1416 {
1417 static const char res[] = "WINEPRELOADRESERVE=";
bfac60bfe… Alex*1418 if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
92425aab6… Alex*1419 p++;
1420 }
b1abca8a5… Alex*1421
3b8ab28c4… Alex*1422 av = (struct wld_auxv *)(p+1);
9f33a4b10… Alex*1423 page_size = get_auxiliary( av, AT_PAGESZ, 4096 );
b1abca8a5… Alex*1424 page_mask = page_size - 1;
1425
ac1761d1d… Alex*1426 preloader_start = (char *)((unsigned long)_start & ~page_mask);
fe031c937… Alex*1427 preloader_end = (char *)((unsigned long)(_end + page_mask) & ~page_mask);
92425aab6… Alex*1428
b1abca8a5… Alex*1429 #ifdef DUMP_AUX_INFO
092ac1fbf… Alex*1430 wld_printf( "stack = %p\n", *stack );
fe031c937… Alex*1431 for( i = 0; i < *pargc; i++ ) wld_printf("argv[%lx] = %s\n", i, argv[i]);
b1abca8a5… Alex*1432 dump_auxiliary( av );
1433 #endif
1434
1435
df8c5a37e… Alex*1436 if (reserve) preload_reserve( reserve );
b1abca8a5… Alex*1437 for (i = 0; preload_info[i].size; i++)
13029a253… Alex*1438 {
0a0862001… Alex*1439 if ((char *)av >= (char *)preload_info[i].addr &&
1440 (char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
1441 {
df8c5a37e… Alex*1442 remove_preload_range( i );
0a0862001… Alex*1443 i--;
1444 }
1445 else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
1446 MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 ) == (void *)-1)
13029a253… Alex*1447 {
7a4d57502… Alex*1448
0ad8bb4ec… Andr*1449 if (preload_info[i].addr >= (void *)0x10000
1450 #ifdef __aarch64__
1451 && preload_info[i].addr < (void *)0x7fffffffff
1452 #endif
1453 )
7a4d57502… Alex*1454 wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
1455 preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size );
df8c5a37e… Alex*1456 remove_preload_range( i );
13029a253… Alex*1457 i--;
1458 }
1459 }
b1abca8a5… Alex*1460
0216c404d… Alex*1461
1462
13029a253… Alex*1463 if (is_addr_reserved( (char *)0x80000000 - page_size ))
1464 wld_mprotect( (char *)0x80000000 - page_size, page_size, PROT_EXEC | PROT_READ );
0216c404d… Alex*1465
b1abca8a5… Alex*1466
c3193925d… Alex*1467 map_so_lib( argv[1], &main_binary_map );
b1abca8a5… Alex*1468
1469
1470 interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
1471 map_so_lib( interp, &ld_so_map );
1472
1473
60fb3d4b6… Alex*1474 wine_main_preload_info = find_symbol( &main_binary_map, "wine_main_preload_info", STT_OBJECT );
b1abca8a5… Alex*1475 if (wine_main_preload_info) *wine_main_preload_info = preload_info;
1476 else wld_printf( "wine_main_preload_info not found\n" );
1477
9f33a4b10… Alex*1478 #define SET_NEW_AV(n,type,val) new_av[n].a_type = (type); new_av[n].a_un.a_val = (val);
1479 SET_NEW_AV( 0, AT_PHDR, (unsigned long)main_binary_map.l_phdr );
1480 SET_NEW_AV( 1, AT_PHENT, sizeof(ElfW(Phdr)) );
1481 SET_NEW_AV( 2, AT_PHNUM, main_binary_map.l_phnum );
1482 SET_NEW_AV( 3, AT_PAGESZ, page_size );
1483 SET_NEW_AV( 4, AT_BASE, ld_so_map.l_addr );
1484 SET_NEW_AV( 5, AT_FLAGS, get_auxiliary( av, AT_FLAGS, 0 ) );
1485 SET_NEW_AV( 6, AT_ENTRY, main_binary_map.l_entry );
a2d76cb43… Alex*1486 SET_NEW_AV( 7, AT_NULL, 0 );
9f33a4b10… Alex*1487 #undef SET_NEW_AV
1488
f558741fa… Alex*1489 i = 0;
1490
4d9f3dfae… Alex*1491 if (is_in_preload_range( av, AT_SYSINFO ) || is_in_preload_range( av, AT_SYSINFO_EHDR ))
1492 {
1493 delete_av[i++].a_type = AT_SYSINFO;
1494 delete_av[i++].a_type = AT_SYSINFO_EHDR;
1495 }
f558741fa… Alex*1496 delete_av[i].a_type = AT_NULL;
1497
c3193925d… Alex*1498
c20d6c409… Alex*1499 set_process_name( *pargc, argv );
c3193925d… Alex*1500 pargc[1] = pargc[0] - 1;
1501 *stack = pargc + 1;
1502
f558741fa… Alex*1503 set_auxiliary_values( av, new_av, delete_av, stack );
b1abca8a5… Alex*1504
1505 #ifdef DUMP_AUX_INFO
092ac1fbf… Alex*1506 wld_printf("new stack = %p\n", *stack);
fe031c937… Alex*1507 wld_printf("jumping to %p\n", (void *)ld_so_map.l_entry);
b1abca8a5… Alex*1508 #endif
1172754fc… Alex*1509 #ifdef DUMP_MAPS
1510 {
1511 char buffer[1024];
1512 int len, fd = wld_open( "/proc/self/maps", O_RDONLY );
1513 if (fd != -1)
1514 {
1515 while ((len = wld_read( fd, buffer, sizeof(buffer) )) > 0) wld_write( 2, buffer, len );
1516 wld_close( fd );
1517 }
1518 }
1519 #endif
b1abca8a5… Alex*1520
1521 return (void *)ld_so_map.l_entry;
1522 }
bd2d79524… Ken *1523
966233aee… Jino*1524 #pragma GCC visibility pop
1525
a0ab2a7b0… Seba*1526 #endif