From 1a5ef5ba1378e28859bf934865c94e8a8c2e7acb Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Wed, 9 Aug 2023 00:25:18 -0700 Subject: [PATCH] Mint APE Loader 1.6 This change fixes a bug with loading pure bss program headers. --- ape/ape-m1.c | 46 +++++++++++++++++++++++------------ ape/ape.S | 34 +++++++++++++------------- ape/apeuninstall.sh | 1 + ape/loader.c | 47 ++++++++++++++++++++++++------------ ape/start.S | 2 +- build/bootstrap/ape.aarch64 | Bin 9304 -> 9360 bytes build/bootstrap/ape.elf | Bin 9448 -> 9454 bytes build/bootstrap/ape.macho | Bin 9448 -> 9454 bytes build/bootstrap/ape.silicon | Bin 35160 -> 35160 bytes libc/calls/execve-sysv.c | 4 +-- tool/decode/pe2.c | 4 ++- 11 files changed, 87 insertions(+), 51 deletions(-) diff --git a/ape/ape-m1.c b/ape/ape-m1.c index 86c282074..1cd64af16 100644 --- a/ape/ape-m1.c +++ b/ape/ape-m1.c @@ -544,8 +544,9 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, /* load elf */ for (i = 0; i < e->e_phnum; ++i) { + void *addr; + unsigned long size; if (p[i].p_type != PT_LOAD) continue; - if (!p[i].p_memsz) continue; /* configure mapping */ prot = 0; @@ -556,36 +557,51 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd, /* load from file */ if (p[i].p_filesz) { - void *addr; int prot1, prot2; - unsigned long size; + unsigned long wipe; prot1 = prot; prot2 = prot; + /* + * when we ask the system to map the interval [vaddr,vaddr+filesz) + * it might schlep extra file content into memory on both the left + * and the righthand side. that's because elf doesn't require that + * either side of the interval be aligned on the system page size. + * + * normally we can get away with ignoring these junk bytes. but if + * the segment defines bss memory (i.e. memsz > filesz) then we'll + * need to clear the extra bytes in the page, if they exist. + * + * since we can't do that if we're mapping a read-only page, we'll + * actually map it with write permissions and protect it afterward + */ a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */ b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */ c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */ - if (b > c) b = c; - if (c > b && (~prot1 & PROT_WRITE)) { + wipe = MIN(b - a, c - a); + if (wipe && (~prot1 & PROT_WRITE)) { prot1 = PROT_READ | PROT_WRITE; } addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz)); size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz; rc = (long)mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz); if (rc < 0) Pexit(exe, rc, "prog mmap"); - if (c > b) Bzero((void *)(dynbase + a), b - a); + if (wipe) Bzero((void *)(dynbase + a), wipe); if (prot2 != prot1) { rc = mprotect(addr, size, prot2); if (rc < 0) Pexit(exe, rc, "prog mprotect"); } - } - - /* allocate extra bss */ - a = p[i].p_vaddr + p[i].p_filesz; - a = (a + (pagesz - 1)) & -pagesz; - b = p[i].p_vaddr + p[i].p_memsz; - if (b > a) { + /* allocate extra bss */ + if (c > b) { + flags |= MAP_ANONYMOUS; + rc = (long)mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0); + if (rc < 0) Pexit(exe, rc, "extra bss mmap"); + } + } else { + /* allocate pure bss */ + addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz)); + size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz; flags |= MAP_ANONYMOUS; - rc = (long)mmap((void *)(dynbase + a), b - a, prot, flags, -1, 0); + rc = (long)mmap(addr, size, prot, flags, -1, 0); if (rc < 0) Pexit(exe, rc, "bss mmap"); } } @@ -861,7 +877,7 @@ int main(int argc, char **argv, char **envp) { } else if (argc < 2) { Emit("usage: ape PROG [ARGV1,ARGV2,...]\n" " ape - PROG [ARGV0,ARGV1,...]\n" - "actually portable executable loader silicon 1.5\n" + "actually portable executable loader silicon 1.6\n" "copyright 2023 justine alexandra roberts tunney\n" "https://justine.lol/ape.html\n"); _exit(1); diff --git a/ape/ape.S b/ape/ape.S index a2b5b1c17..aff5c6727 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -610,7 +610,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang // extract the loader into a temp folder, and use it to // load the APE without modifying it. .ascii "[ x\"$1\" != x--assimilate ] && {\n" - .ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.5\"\n" + .ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.6\"\n" .ascii "[ -x \"$t\" ] || {\n" .ascii "mkdir -p \"${t%/*}\" &&\n" .ascii "dd if=\"$o\" of=\"$t.$$\" skip=" @@ -818,7 +818,7 @@ ape.ident: .long 1 1: .asciz "APE" 2: .balign 4 -3: .long 105000000 +3: .long 106000000 4: .size ape.ident,.-ape.ident .type ape.ident,@object .previous @@ -1052,11 +1052,11 @@ PEIMPS = 0b11000000000000000000000001000000 .balign __SIZEOF_POINTER__ ape_pe: .ascin "PE",4 .short kNtImageFileMachineNexgen32e - .stub ape_pe_shnum,short // NumberOfSections + .short ape_pe_shnum // NumberOfSections .long 0x5c64126b // TimeDateStamp .long 0 // PointerToSymbolTable .long 0 // NumberOfSymbols - .stub ape_pe_optsz,short // SizeOfOptionalHeader + .short ape_pe_optsz // SizeOfOptionalHeader .short PEEXE // Characteristics .short kNtPe64bit // Optional Header Magic .byte 14 // MajorLinkerVersion @@ -1080,25 +1080,25 @@ ape_pe: .ascin "PE",4 .long ape_pe_sizeofheaders // SizeOfHeaders .long 0 // Checksum .short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console - .stub v_ntdllchar,short // DllCharacteristics - .quad 0x0000000000100000 // StackReserve - .quad 0x00000000000fc000 // StackCommit + .short v_ntdllchar // DllCharacteristics + .quad ape_stack_memsz2 // StackReserve + .quad 64 * 1024 // StackCommit .quad 0 // HeapReserve .quad 0 // HeapCommit .long 0 // LoaderFlags .long 2 // NumberOfDirectoryEntries .long 0,0 // ExportsDirectory - .stub ape_idata,long // ImportsDirectory - .stub ape_idata_idtsize,long // ImportsDirectorySize + .long ape_idata // ImportsDirectory + .long ape_idata_idtsize // ImportsDirectorySize .endobj ape_pe,globl .previous .section .pe.sections,"a",@progbits .ascin ".text",8 // Section Name - .stub ape_text_memsz,long // Virtual Size or Physical Address - .stub ape_text_rva,long // Relative Virtual Address - .stub ape_text_filesz,long // Physical Size - .stub ape_text_offset,long // Physical Offset + .long ape_text_memsz // Virtual Size or Physical Address + .long ape_text_rva // Relative Virtual Address + .long ape_text_filesz // Physical Size + .long ape_text_offset // Physical Offset .long 0 // Relocation Table Offset .long 0 // Line Number Table Offset .short 0 // Relocation Count @@ -1108,10 +1108,10 @@ ape_pe: .ascin "PE",4 .section .pe.sections,"a",@progbits .ascin ".data",8 // Section Name - .stub ape_ram_memsz,long // Virtual Size or Physical Address - .stub ape_ram_rva,long // Relative Virtual Address - .stub ape_ram_filesz,long // Physical Size - .stub ape_ram_offset,long // Physical Offset + .long ape_ram_memsz // Virtual Size or Physical Address + .long ape_ram_rva // Relative Virtual Address + .long ape_ram_filesz // Physical Size + .long ape_ram_offset // Physical Offset .long 0 // Relocation Table Offset .long 0 // Line Number Table Offset .short 0 // Relocation Count diff --git a/ape/apeuninstall.sh b/ape/apeuninstall.sh index 4279e219e..2274462de 100755 --- a/ape/apeuninstall.sh +++ b/ape/apeuninstall.sh @@ -38,6 +38,7 @@ for x in .ape \ .ape-1.3 \ .ape-1.4 \ .ape-1.5 \ + .ape-1.6 \ .ape-blink-0.9.2 \ .ape-blink-1.0.0; do rm -f \ diff --git a/ape/loader.c b/ape/loader.c index ffbdb3838..065b0444a 100644 --- a/ape/loader.c +++ b/ape/loader.c @@ -698,6 +698,8 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, /* load elf */ for (i = 0; i < e->e_phnum; ++i) { + void *addr; + unsigned long size; if (p[i].p_type != PT_LOAD) continue; /* configure mapping */ @@ -707,38 +709,53 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd, if (p[i].p_flags & PF_W) prot |= PROT_WRITE; if (p[i].p_flags & PF_X) prot |= PROT_EXEC; - /* load from file */ if (p[i].p_filesz) { - void *addr; + /* load from file */ int prot1, prot2; - unsigned long size; + unsigned long wipe; prot1 = prot; prot2 = prot; + /* + * when we ask the system to map the interval [vaddr,vaddr+filesz) + * it might schlep extra file content into memory on both the left + * and the righthand side. that's because elf doesn't require that + * either side of the interval be aligned on the system page size. + * + * normally we can get away with ignoring these junk bytes. but if + * the segment defines bss memory (i.e. memsz > filesz) then we'll + * need to clear the extra bytes in the page, if they exist. + * + * since we can't do that if we're mapping a read-only page, we'll + * actually map it with write permissions and protect it afterward + */ a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */ b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */ c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */ - if (b > c) b = c; - if (c > b && (~prot1 & PROT_WRITE)) { + wipe = MIN(b - a, c - a); + if (wipe && (~prot1 & PROT_WRITE)) { prot1 = PROT_READ | PROT_WRITE; } addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz)); size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz; rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os); if (rc < 0) Pexit(os, exe, rc, "prog mmap"); - if (c > b) Bzero((void *)(dynbase + a), b - a); + if (wipe) Bzero((void *)(dynbase + a), wipe); if (prot2 != prot1) { rc = Mprotect(addr, size, prot2, os); if (rc < 0) Pexit(os, exe, rc, "prog mprotect"); } - } - - /* allocate extra bss */ - a = p[i].p_vaddr + p[i].p_filesz; - a = (a + (pagesz - 1)) & -pagesz; - b = p[i].p_vaddr + p[i].p_memsz; - if (b > a) { + /* allocate extra bss */ + if (c > b) { + flags |= MAP_ANONYMOUS; + rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os); + if (rc < 0) Pexit(os, exe, rc, "extra bss mmap"); + } + } else { + /* allocate pure bss */ + addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz)); + size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz; flags |= MAP_ANONYMOUS; - rc = Mmap((void *)(dynbase + a), b - a, prot, flags, -1, 0, os); + rc = Mmap(addr, size, prot, flags, -1, 0, os); if (rc < 0) Pexit(os, exe, rc, "bss mmap"); } } @@ -874,7 +891,7 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) { Print(os, fd, "NAME\n" "\n" - " actually portable executable loader version 1.5\n" + " actually portable executable loader version 1.6\n" " copyright 2023 justine alexandra roberts tunney\n" " https://justine.lol/ape.html\n" "\n" diff --git a/ape/start.S b/ape/start.S index c04b33d43..7a99d6f38 100644 --- a/ape/start.S +++ b/ape/start.S @@ -65,7 +65,7 @@ ape.ident: .long 1 1: .asciz "APE" 2: .balign 4 -3: .long 105000000 +3: .long 106000000 4: .size ape.ident,.-ape.ident .type ape.ident,@object diff --git a/build/bootstrap/ape.aarch64 b/build/bootstrap/ape.aarch64 index a46b1f5155093f5ba23fce5bd9b38e65a88160d7..329e3eb31d06b9f7c7f4fed5859319cd91dd3c0d 100755 GIT binary patch delta 2706 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 R9x7bGZHr1s3$IwT^xv4HEP((3 delta 2616 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 JCaZrV{||*$)jt3L delta 2459 zcmXw5ZEzFU72PMvVDq)|2Z_^?Rx;aS1Eo>ZB)bKI1uJ|Puf{aM;4n_&1j;0sc8HNN z6oa5^P4d{;l(PN$(dp1h+A>Xkv>^=+EkssgusxHEYo=+Tos=?6W{m6>u!{P{E2q6#O8gT#_^BjCC9m4u6h6idx#377d)#e`#MwOe#mIH`vHM)f zKK6`zvE=paSaL&h{RWfwtt0+9S)cCa>y@>-{b%L(z$R`gWa6tdog2thnY^F;ek0eL zsUTMWVC1Qi^2K!KK-hxmwQo(CqVzAm3=Q{m9yNVQ#6lLzmJ9Gw@)Zj9Mo%Gwm4 zF!>eJc~x*=@=v_){m=I)mzQ6D4bXMP6vuu{Nf_2O%D_bjd%p+}RUpdtk3@0;7 zrM6+!OQYVcexq7^&*1suX|h2`DlrVEi0evBAf}y7jQEhDos*rb;5FTLMQwBX>__4tH>kgeuI@wk%yZi2mU=>&ixEavUil4Ho8DOqePAI^JI6H5;me~bREk$VOvt(1$v>T$LiPeaz4WbZ|j`x~%15;7irDnJRp3a!LNJrQr zBrth>E%6;O!&w=+cicuNvv@~v+}1l&$4&EdX?|hk%RYFwx|HfjrZ)I3$t(^O+T0ZcX3BMwq zh6J6G>0_ua{-GJ~M?lbUQ(l!Pr{p6@m$Wk^uRddF`JDnfJ1R1dK&fe`jTwB%T)JIR zcRrD{dQ?$y#|pzfK(I{y0mb_W-WbU%@oj_;v|^uvLgM|TT_?HW3~7AV3rB-+^?a3$&T>WhXpXv!=9V)*ZoRZvH| zA!tC0POJoI1W;tOm0GfLaVL1-J(3N+W_4oL}lJ5 zG$n8~2&HpoO1mI;zl?QpebD?hj`=l-m`A*jCFlF4q}^(tMQ1~Zz);>U7KsmL(<4GF#c4j1H^dS5Eu5H+^o?rAnQ4~wJ4M7^rlf+|H(v0R=P zg2GPEMPcFFP^BPL@Rmg^E=LeYVa&G?&Va@7zf=4yhHq!$+f+9R?z+kB@d6*8A#67?Ks5^BHXxZwF{X{z-3QI5Fm!M%c>( z0nTi+qefI)z3nUF+8Ed-2}0N6+7GgN=kQ8s-bD7!>V!`?3%YQN*fl(fG1So&?+_v| z+ba54Tn=NkFun<+Ss068ydaDk7)ONh0E{<;0S%Q5M1?gSmIs5Z_jkM7=4`po26O3f zvf6N-U?%@~jnh>kdAr=pbH2(By*g87p{h!Ec61B#-1g{_XOH4hlaG2gZuovKp8@V8 zhq2{d3f3JDo)$yRM-u~h?KyM1gp2*h_xZJiU#!7N!Qd||CF!*2KOZ&uU?T5byeR_S z6;FC^yR5vj>@Y$^mi_L7bAK*8^5+$p-rJ zb?%bN2iQ87Do;gEq1L;x#CyHH?%b+esP@M3UsP?G>Fx+6-;A9Px&Nx!#vVDoX8vpJ E|Lq@>u>b%7 diff --git a/build/bootstrap/ape.macho b/build/bootstrap/ape.macho index 7be50986c51019def9b63a26490e4eb02921a38a..4987e2ff7dbf4f51afe0600af4d91ca81c38ac76 100755 GIT binary patch delta 2622 zcma)8YitzP6`t8$!!`lWdNFi^inMD_U>yYQibr;FARgE?_nNyriV5KGaKobrSCI?5 z*hq#2#-nmO8L4RKk48$XidIF9R4D-|#BJz$4Sqmd5mTa25HTnuYc>Xlw&szP>30XW zQvcOIJm=hd?svX(?sxCqBE3t0a#0c0k@?50$;0 zd!nt=8rQ95ya%g}A~WF`)t@x~pyuK5Ms+^nOkK_JFOW6{GL?+?6Q`dV-I*Y=&0el$UnXyTk=2t!leTN#h#Nuv8;HEFpN*UaP7q#Ty$kG)Fg zSw!fMJx>kdM5WR+CKlC7QUbSh*6qoNl=jZ?KYc zBt0%G#yc2kusY_%kw!62z%z+&-YVarn-dk|I9y`3`k9IS5L*?Z53Ulk%}+28B3=?s z^L{4Zq>)h;8DKTtq!xi~&BP=DW-iAPriKv~MGOMcxkxvw8F(7>67w#P5^r0W%}yd{ zHozILixS=%rq)u=e=2RTGILtpO4t2sywWtkoaTQU4m;?(-l2wlnOW|)Ec1f<^=5s9 zxA=+P6Cmb1K|4&0vFzniMNaI>Lc&-0OScGL>n~j=<|b6;TqJxG3aS$TnVf zQmteBekwL1gh$X43H^&@fh~Eu*LSntdKpQfX5cY)#+abc_M|;Wz%@DEXKT8r1_K9gv z2-Ed0M}Si~zvmg|O`?T~ygM(8`I(rf{3~XaIsZg8k-y~9k&DDC8-ljeiJr8wtcN6e ziBjK76ZyUW%{mG}r>z|_<(F9PcC~KrN=-i#2S+(uOU*+B7ULI5q=zN0QDx~h>OIsf zDsb~h`blDxD9d|EqQ`|iD++lFkkmPsqk2AGdVB1MPoQP0g;=rU*hA4HLe2UR4$MAO z*>?tQl$81+OQrK$2;K7Hfy>gcU58C84r%^ z`!FOWS?H4LBd zZVVFxeN~L>7;zJb>)=dSV5bUQ&)}Q3elEe+`-5U0g={#}Af}TA*qb!vY#+X@kY0T* zP7+C|ORw=Don8yMR0zvl=F|9jt$W0y>9^&Ro{Ue^|Li#_yI&tQmxZahH$csns36z* z26{tq7lmAbGE4nVir;}88?4G%#CmBisX5Og7ers{2=3G zJzAF+98*f_3gPz|G~Z6Dp}qHm7{%gr^$NeXmdL%@`Xn|f3E1gLKA7ak)lNi+L)9)4 zv=&c4aGa)%;3XI}i@S7J(ri>S43cf%FGNMAK>^i*bIusaPD~}PWOAj|RKCvS+l&tp zYqcNr_DmvuKo;1SN+rUJ)M6@bz;!aK86x`7Lz4Kg%bi!27pQ!WC2sFK4NYmiN!5`` zqk?8DuBAJ$+kx`?HehjGY3Q<86x=8Xn z;y#LMtA$v!^+4T46riS@X9#d?7k6|2|K$bItQ z6Ky?}@0d9O6nOwF$gy|;a9g&HgGKk318fPvcwxBh5g0m93e|h!!+ki$u>qkivQ0cd z5R~%MZfJPSV$@qaB3S88AX_E!hj%|88w7{lP)J7IfM+E(Ah?S+X+y4wdbfmPsJ>A} zZBCdd$qscj;Wv`}QPDyOZimMeC}=SZKeSMq4`aG8X2X~*j4Bw7!gvnG>%s`YFoiJ@ z#&2Pe!{@}~{_19JleSsgqHXQb8YzE7?M3Blr!`<((q1h@t?$Z=-@xNjCKVUhC(38a z^u&d7*>g2$|4G>{|Hh65=H_+)j`4fNckVlmk8g5Qe`;H|Z$ zYGNw?cgNv(V@|0G)uXA~rbyCR95aM5ej%1G{=yCTqgYwY!q)H-mS@=I6;<-{cB~>L$LzL>Rq_(MuVU`T8Q_4UU1{X^XVB3~y+ooXf9tQE!^C#fC#{M7}Q5GQ@U5bi#&srR^M}p7EL3`qq z4+0(FIvz`ScX5&Z*C~eQ^Dj@mTDkq%cf(gb6Lz#`_IxjFU#;3LFFcj3{+0Z1sutF3 delta 2473 zcma)8YitzP6`s4h2J@WtgT!e`yK7Gy8z^F%CYdP^JTQyT;8{Tf2nRWd6DUe;w<55{ zPz(zlugYaKDPj7QstPG-i<|zVmF#2Bc$Z3E&5Y?A z^$i;>-nX9kXJmh}n{QCo8O|S+-y#d*mO>W(N>kZ^bfv}nDd;z|z3Fmt=Y0Efl2jl% zXDFozCLLUwNm{GrY%ood4(yFExqA|lvnp!)p>6gAlfOTX^)`EN`Qvi-UsK|vY9?I? zSIgllF>LWMg9rXsCxgI{PqwL0Xiy~EuBrOLyCO#CMRFQrPM5MS$tNs+)pB2!fR@ES z_P_J*AfRkcKJ*G)n_8co6@q-SQBCAX>)l^XZ9}T_!wO+<-wDgzFG6kK$%LjP3UY-D z$wW>*xn8xj{C>@B>sL*;o|*2l+4c(7QA2j7R_d5f+R(l-s>_>hdbUb!!>XS`zT1LE zweXI~bA>bH0FY#27)TK}l$h|CayK*LL#B3KcCP`~RNGax(Tyy!)eMufZ(yg9jw!K$`s1(Q^~*Qy(svdS#A!VS=L#;k<~%oZYm#p`Q{Z;zSo z%FutyZFJL%winB7xjR*Eil0yMiz8nQfVO+Puln{p`BR;tx=3=D77Zb?U-qW4WOdsiuxHsuZYv2pj$G14B5rs zx8nUUC^p=ZSLMhp`2f@~SZCBKtPv~}!Dl+a^ zVLAs0lEvSncppI{Bt3ct2@3NNzYwT3^xcY2o%L+?qk3Y3J0!ugAU@ z5f0OeU?Z9-u;)fbsV8Su6~+OTXym1M}PFPYk)C9nLW8N5SwULENMp^@!R;We4P zB6n->oVbR`jfOi~bUR?DLYT##YMi$C2XZq1mQ*iEr?8at^>T7h-;_)Y=yrdQ2xj#9 zwZ-&2J_h(@66!AWuFHY)}&x&!LM;yumVL3a5onnBQ@YS;hf3lH3B_{vgq+_6( zdSYTfnYa7PvD~1`XU^f-ET3GZl4gK0_H`7d+shPC;7>vX1`(d`y_yNxmzmCokB8C` z-5v}bXT@j4gh5QC)V&twrXWO-a7ljNa@xTTci9p#b%3$f#O+gSh1-ED8&AdGGqt;7 zKW51dqn0+hYpy<)59z-TBgdqiyh!|}fg815usWJ~s~p=_d@xlbhMAp(;{^tXQJ13X z>-0?q5@{hsAcHq6yTt%(_kTAIP@dE`BSFE{7Q<;)o;Msg-6Ke4-6uFD{AwUd=d7f5 zQSLs3bzwuX`Djc4i(D3*P}N z1)u`A3~X^Z0yqj|zRhqND31Sy;^#1YI}_iax=ApH*r>h<0k#SX8GP7(6C?KYGbn%0 zTtOqa<@u3UZ-YDm+HKnJsv}`gR&Xw0v_-rfzzO+By@}z(m}{9~KL-y`W}+R{BHOCg zFNteopj8rpuEVuojOw4qE1_vKIXkNo0ihOj;Wn}BIEgVd&=vnMEHK+D`dC;FVYLvx z2BAp^3n6?<2-Ogd3gH0=uL%JhDjA3hX*why0@?5G_FCs|z0U!1sjyyUx=%2Rf4Ii& zDv|tM-j%suW`|#%C9_avg*PXxrOHjY@&wFDfMIjOaffwfJBn=U=)d4Bi$e{Wm>URx#rU zOhlCZ-h*Wc*5s`%t7a|UjR+(4lg`q}Vl5On7{9!7p!M1GG=t!uCrF!~RD>iwX6KE7C9E3d0t z1SR}_UHIa?JfF?&o@-C6=&Zoz0&I%UhDl_4)SE1i%X@DWQK=;d-j}cU7FRsL)_YWO uI(izp-m@j%>+kjERc1rAH&6V$a_cN_3DaMXT?l!9uWn_JoLE!y3i}UQ2$Y-v diff --git a/build/bootstrap/ape.silicon b/build/bootstrap/ape.silicon index 179a84f947636f268d5d13d4e1f22c0f3e3ae2aa..3fd81f30be31a50cf5ee583ac622e17a79ea8f1c 100755 GIT binary patch delta 2109 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, pe->FileHeader.SizeOfOptionalHeader)); - ShowSections(pecheckaddress(mz, mzsize, pe + 1, + ShowSections(pecheckaddress(mz, mzsize, + (char *)(pe + 1) + + pe->OptionalHeader.NumberOfRvaAndSizes * 8, pe->FileHeader.NumberOfSections * sizeof(struct NtImageSectionHeader)), pe->FileHeader.NumberOfSections);