Skip to content

Commit 23611cd

Browse files
committed
Talk more about alignment
1 parent 62a97c9 commit 23611cd

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

ape/specification.md

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ different OSes define incompatible ABIs.
292292

293293
While it was possible to polyglot PE+ELF+MachO to create multi-OS
294294
executables, it simply isn't possible to do that same thing for
295-
DLL+DLIB+SO. Therefore, in order to have DSOs, APE would need to either
295+
DLL+DYLIB+SO. Therefore, in order to have DSOs, APE would need to either
296296
choose one of the existing formats or invent one of its own, and then
297297
develop its own parallel ecosystem of extension software. In the future,
298298
the APE specification may expand to encompass this. However the focus to
@@ -459,7 +459,7 @@ can't modify itself at the same time. The way Cosmopolitan solves this
459459
is by defining a special part of the binary called `.text.privileged`.
460460
This section is aligned to page boundaries. A GNU ld linker script is
461461
used to ensure that code which morphs code is placed into this section,
462-
through the use of a header-define cosmo-specific keyword `privileged`.
462+
through the use of a header-defined cosmo-specific keyword `privileged`.
463463
Additionally, the `fixupobj` program is used by the Cosmo build system
464464
to ensure that compiled objects don't contain privileged functions that
465465
call non-privileged functions. Needless to say, `mprotect()` needs to be
@@ -482,7 +482,7 @@ The Actually Portable Executable Thread Information Block (TIB) is
482482
defined by this version of the specification as follows:
483483
484484
- The 64-bit TIB self-pointer is stored at offset 0x00.
485-
- The 64-bit TIB self-pointer is stored at offset 0x30.
485+
- The 64-bit TIB self-pointer is also stored at offset 0x30.
486486
- The 32-bit `errno` value is stored at offset 0x3c.
487487
488488
All other parts of the thread information block should be considered
@@ -584,25 +584,30 @@ imposed by the executable formats that APE wraps.
584584
program segments once the invariant is restored. ELF loaders will
585585
happily map program headers from arbitrary file intervals (which may
586586
overlap) onto arbitrarily virtual intervals (which don't need to be
587-
contiguous). in order to do that, the loaders will generally use
588-
UNIX's mmap() function which needs to have both page aligned
589-
addresses and file offsets, even though the ELF programs headers
590-
themselves do not. Since program headers start and stop at
591-
potentially any byte, ELF loaders tease the intervals specified by
592-
program headers into conforming to mmap() requirements by rounding
593-
out intervals as necessary in order to ensure that both the mmap()
594-
size and offset parameters are page-size aligned. This means with
595-
ELF, we never need to insert any empty space into a file when we
596-
don't want to; we can simply allow the offset to drift apart from the
597-
virtual offset.
598-
599-
2. PE doesn't care about congruence and instead specifies a second kind
600-
of alignment. The minimum alignment of files is 512 because that's
601-
what MS-DOS used. Where things get hairy is with PE's SizeOfHeaders
602-
which has complex requirements. When the PE image base needs to be
603-
skewed, Windows imposes a separate 64kb alignment requirement on the
604-
image base. Therefore an APE executable's `__executable_start` should
605-
be aligned on at least a 64kb address.
587+
contiguous). In order to do that, the loaders will generally use
588+
UNIX's mmap() function which is more restrictive and only accepts
589+
addresses and offsets that are page aligned. To make it possible to
590+
map an unaligned ELF program header that could potentially start and
591+
stop at any byte, ELF loaders round-out the intervals, which means
592+
adjacent unrelated data might also get mapped, which may need to be
593+
explicitly zero'd. Thanks to the cleverness of ELF, it's possible to
594+
have an executable file be very tiny, without needing any alignment
595+
bytes, and it'll be loaded into a properly aligned virtual space
596+
where segments can be as sparse as we want them to be.
597+
598+
2. PE doesn't care about congruence and instead defines two separate
599+
kinds of alignment. First, PE requires that the layout of segment
600+
memory inside the file be aligned on at minimum the classic 512 byte
601+
MS-DOS page size. This means that, unlike ELF, some alignment padding
602+
may need to be encoded into the file, making it slightly larger. Next
603+
PE imposes an alignment restriction on segments once they've been
604+
mapped into the virtual address space, which must be rounded to the
605+
system page size. Like ELF, PE segments need to be properly ordered
606+
but they're allowed to drift apart once mapped in a non-contiguous
607+
sparsely mapped way. When inserting shell script content at the start
608+
of a PE file, the most problematic thing is the need to round up to
609+
the 64kb system granularity, which results in a lot of needless bytes
610+
of padding being inserted by a naive second-pass linker.
606611

607612
3. Apple's Mach-O format is the strictest of them all. While both ELF
608613
and PE are defined in such a way that invites great creativity, XNU

0 commit comments

Comments
 (0)