Tune the page sizes

This commit is contained in:
Justine Tunney 2023-07-24 00:49:06 -07:00
parent ff198e7577
commit 94ea34367a
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
12 changed files with 56 additions and 178 deletions

View file

@ -72,7 +72,7 @@ SECTIONS {
KEEP(*(SORT_NONE(.fini)))
} =0x1f2003d5
.privileged ALIGN(CONSTANT(MAXPAGESIZE)) : {
.privileged ALIGN(CONSTANT(COMMONPAGESIZE)) : {
__privileged_start = .;
*(.privileged*)
} =0x1f2003d6
@ -119,8 +119,8 @@ SECTIONS {
_etext = .;
PROVIDE(etext = .);
. = ALIGN(CONSTANT(MAXPAGESIZE));
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
. = ALIGN(CONSTANT(COMMONPAGESIZE));
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
.eh_frame : ONLY_IF_RW {
KEEP(*(.eh_frame))
@ -209,6 +209,7 @@ SECTIONS {
*(.bss .bss.* .gnu.linkonce.b.*)
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
*(COMMON)
. = ALIGN(CONSTANT(COMMONPAGESIZE));
}
_bss_end__ = .;

View file

@ -224,7 +224,7 @@ stub: mov $0x40,%dl // *literally* dos
3: .byte 0xbd,0,0 // a.k.a. mov imm,%bp
jmp pc // real mode, is real
jmp _start // surprise it's unix
.endfn stub
.endfn stub,globl
/*
αcτµαlly pδrταblε εxεcµταblε § ibm personal computer
@ -1073,25 +1073,10 @@ ape_pe: .ascin "PE",4
.quad 0 // HeapReserve
.quad 0 // HeapCommit
.long 0 // LoaderFlags
.long 16 // NumberOfDirectoryEntries
.long 2 // NumberOfDirectoryEntries
.long 0,0 // ExportsDirectory
.stub ape_idata,long // ImportsDirectory
.stub ape_idata_idtsize,long // ImportsDirectorySize
.long 0,0 // ResourcesDirectory
.long 0,0 // ExceptionsDirectory
.long 0,0 // SecurityDirectory
.long 0,0 // BaseRelocationTable
.long 0,0 // DebugDirectory
.long 0,0 // DescriptionString
.long 0,0 // MachineSpecific
.long 0,0 // ThreadLocalStorage
.long 0,0 // LoadConfigurationDirectory
.long 0,0 // BoundImportDirectory
.stub ape_idata,long // ImportAddressDirectory
.stub ape_idata_iatsize,long // ImportAddressDirectorySize
.long 0,0 // DelayImportDescriptor
.long 0,0 // ComPlusRuntimeHeader
.long 0,0 // Reserved
.endobj ape_pe,globl
.previous

View file

@ -390,7 +390,7 @@ SECTIONS {
} :Tls :Rom
/*END: Read Only Data */
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
. = DATA_SEGMENT_RELRO_END(0, .);
/* this only tells the linker about the layout of uninitialized */
@ -461,7 +461,7 @@ SECTIONS {
KEEP(*(.bssepilogue))
. = ALIGN(64);
. = ALIGN(CONSTANT(COMMONPAGESIZE));
/*END: NT FORK COPYING */
_end = .;
@ -722,7 +722,7 @@ PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
ape_pe_optsz = ape_pe_sections - (ape_pe + 24);
ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40;
ape_pe_base = IMAGE_BASE_VIRTUAL;
ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;

View file

@ -215,7 +215,7 @@ o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/launch.o \
o/$(MODE)/ape/systemcall.o \
ape/loader.lds
@$(COMPILE) -ALINK.elf $(LINK) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
.PHONY: o/$(MODE)/ape
o/$(MODE)/ape: $(APE_CHECKS) \

View file

@ -888,7 +888,8 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
}
}
if (READ64(M->ehdr.buf) == READ64("MZqFpD='") ||
READ64(M->ehdr.buf) == READ64("jartsr='")) {
READ64(M->ehdr.buf) == READ64("jartsr='") ||
READ64(M->ehdr.buf) == READ64("APEDBG='")) {
for (p = M->ehdr.buf; p < pe; ++p) {
if (READ64(p) != READ64("printf '")) {
continue;

Binary file not shown.

Binary file not shown.

View file

@ -252,7 +252,7 @@ DEFAULT_LDFLAGS += \
-znorelro
else
DEFAULT_LDFLAGS += \
-zmax-page-size=0x1000 \
-zmax-page-size=0x10000 \
-zcommon-page-size=0x1000
endif

View file

@ -3,14 +3,11 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct NtImageImportDescriptor {
union {
uint32_t Characteristics;
uint32_t OriginalFirstThunk;
};
uint32_t ImportLookupTable;
uint32_t TimeDateStamp;
uint32_t ForwarderChain;
uint32_t Name;
uint32_t FirstThunk;
uint32_t DllNameRva;
uint32_t ImportAddressTable;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -11,11 +11,43 @@ struct NtImageOptionalHeader {
uint32_t SizeOfCode;
uint32_t SizeOfInitializedData;
uint32_t SizeOfUninitializedData;
/*
* The address of the entry point relative to the image base when the
* executable file is loaded into memory. For program images, this is
* the starting address. For device drivers, this is the address of
* the initialization function. An entry point is optional for DLLs.
* When no entry point is present, this field must be zero.
*/
uint32_t AddressOfEntryPoint;
uint32_t BaseOfCode;
/*
* The preferred address of the first byte of image when loaded into
* memory; must be a multiple of 64 K. The default for DLLs is
* 0x10000000. The default for Windows CE EXEs is 0x00010000. The
* default for Windows NT, Windows 2000, Windows XP, Windows 95,
* Windows 98, and Windows Me is 0x00400000.
*/
uint64_t ImageBase;
/*
* The alignment (in bytes) of sections when they are loaded into
* memory. It must be greater than or equal to FileAlignment. The
* default is the page size for the architecture.
*/
uint32_t SectionAlignment;
/*
* The alignment factor (in bytes) that is used to align the raw data
* of sections in the image file. The value should be a power of 2
* between 512 and 64 K, inclusive. The default is 512. If the
* SectionAlignment is less than the architecture's page size, then
* FileAlignment must match SectionAlignment.
*/
uint32_t FileAlignment;
uint16_t MajorOperatingSystemVersion;
uint16_t MinorOperatingSystemVersion;
uint16_t MajorImageVersion;
@ -34,7 +66,7 @@ struct NtImageOptionalHeader {
uint64_t SizeOfHeapCommit;
uint32_t LoaderFlags;
uint32_t NumberOfRvaAndSizes;
struct NtImageDataDirectory DataDirectory[kNtImageNumberofDirectoryEntries];
struct NtImageDataDirectory DataDirectory[];
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,139 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/elf/elf.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "third_party/getopt/getopt.internal.h"
#define VERSION \
"apelink v1.0\n" \
"copyright 2023 justine tunney\n" \
"https://github.com/jart/cosmopolitan\n"
#define MANUAL \
" -o OUTPUT INPUT...\n" \
"\n" \
"DESCRIPTION\n" \
"\n" \
" Actually Portable Executable Linker\n" \
"\n" \
" This program may be used to turn ELF executables into\n" \
" APE executables. It's useful for creating fat binaries\n" \
" that run on multiple architectures.\n" \
"\n" \
"FLAGS\n" \
"\n" \
" -h show usage\n" \
" -o OUTPUT set output path\n" \
"\n" \
"ARGUMENTS\n" \
"\n" \
" OUTPUT is your ape executable\n" \
" INPUT may specify multiple APE or ELF builds of the\n" \
" same program for different architectures that\n" \
" shall be merged into a single output file\n" \
"\n"
static const char *prog;
static const char *outpath;
static wontreturn void Die(const char *reason) {
tinyprint(2, prog, ": ", reason, "\n", NULL);
exit(1);
}
static wontreturn void DieSys(const char *thing) {
perror(thing);
exit(1);
}
static wontreturn void ShowUsage(int rc, int fd) {
tinyprint(fd, VERSION, "\nUSAGE\n\n ", prog, MANUAL, NULL);
exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "ho:")) != -1) {
switch (opt) {
case 'o':
outpath = optarg;
break;
case 'h':
ShowUsage(0, 1);
default:
ShowUsage(1, 2);
}
}
if (!outpath) {
Die("need output path");
}
if (optind == argc) {
Die("missing input argument");
}
}
static void HandleInput(const char *inpath) {
int fildes;
ssize_t esize;
Elf64_Ehdr *elf;
if ((fildes = open(inpath, O_RDONLY)) == -1) {
DieSys("open");
}
if ((esize = lseek(fildes, 0, SEEK_END)) == -1) {
DieSys("lseek");
}
if (esize) {
if ((elf = mmap(0, esize, PROT_READ | PROT_WRITE, MAP_SHARED, fildes, 0)) ==
MAP_FAILED) {
DieSys("mmap");
}
if (IsElf64Binary(elf, esize)) {
}
if (munmap(elf, esize)) {
DieSys("munmap");
}
}
if (close(fildes)) {
DieSys("close");
}
}
int main(int argc, char *argv[]) {
int i, opt;
// get program name
prog = argv[0];
if (!prog) prog = "apelink";
// read flags
GetOpts(argc, argv);
// read args
for (i = optind; i < argc; ++i) {
HandleInput(argv[i]);
}
return 0;
}

View file

@ -24,6 +24,7 @@
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
@ -107,12 +108,12 @@ void GetOpts(int argc, char *argv[]) {
}
}
void GetElfHeader(char ehdr[hasatleast 64], const char *image) {
void GetElfHeader(char ehdr[hasatleast 64], const char *image, size_t n) {
char *p;
int c, i;
for (p = image; p < image + 4096; ++p) {
for (p = image; p < image + MIN(n, 4096); ++p) {
if (READ64LE(p) != READ64LE("printf '")) continue;
for (i = 0, p += 8; p + 3 < image + 4096 && (c = *p++) != '\'';) {
for (i = 0, p += 8; p + 3 < image + MIN(n, 4096) && (c = *p++) != '\'';) {
if (c == '\\') {
if ('0' <= *p && *p <= '7') {
c = *p++ - '0';
@ -208,7 +209,7 @@ void GetMachoPayload(const char *image, size_t imagesize, int *out_offset,
void AssimilateElf(char *p, size_t n) {
char ehdr[64];
GetElfHeader(ehdr, p);
GetElfHeader(ehdr, p, n);
memcpy(p, ehdr, 64);
msync(p, 4096, MS_SYNC);
}
@ -232,8 +233,8 @@ void Assimilate(void) {
kprintf("%s: fstat() failed: %m\n", prog);
exit(14);
}
if (st.st_size < 4096) {
kprintf("%s: ape binaries must be at least 4096 bytes\n", prog);
if (st.st_size < 64) {
kprintf("%s: ape binaries must be at least 64 bytes\n", prog);
exit(15);
}
if ((p = mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) ==