unison-runtime-0.0.0
Safe HaskellNone
LanguageHaskell2010

Unison.Runtime.Bundle.MachO

Description

A bundle's program inside a Mach-O executable (macOS), in the section UNISON,uc (see Unison.Runtime.Bundle).

A Mach-O executable is a header, a list of load commands, and the bytes of its segments, in order. Each segment's load command says where its bytes are in the file (fileoff, filesize) and in memory (vmaddr, vmsize), and lists its sections. The last segment is always __LINKEDIT: the symbol table, the dynamic loader's information and the code signature, which other load commands point into by file offset.

unisonrt is linked with -sectcreate UNISON uc, so that the segment __UNISON, holding that one section, is the segment right before __LINKEDIT, in the file and in memory. That makes the section the one place that can grow without moving any code or data: growing it moves only __LINKEDIT, which no code refers to by address, and the load commands say where __LINKEDIT and everything in it now is. Since the program is then part of the image, the code signature covers it, once the executable is signed again.

Field offsets are from mach-o/loader.h.

Synopsis

Documentation

isMachO :: ByteString -> Bool Source #

Whether these are the bytes of a 64-bit little-endian Mach-O file (arm64 and x86-64 macOS)

programSection :: ByteString -> Maybe ByteString Source #

The contents of the section UNISON,uc, if the file has it

setProgramSection :: ByteString -> ByteString -> Either String ByteString Source #

The file with the section UNISON,uc holding these contents instead. Its code signature no longer matches; the caller signs it again. The steps:

  1. Find the segment __UNISON and its section, and check that the segment is the one right before __LINKEDIT, in the file and in memory.
  2. The segment's new size: from its start to the end of the new contents, in whole pages, since segments are mapped by page.
  3. __LINKEDIT moves to just after it, in the file and in memory, by the change in that size.
  4. The load commands are patched: the segment's sizes and the section's, __LINKEDIT's place, and every file offset another load command holds into __LINKEDIT (linkEditOffsetFields).
  5. The new file is the bytes before the segment (with the patched load commands, which are among them), the segment's new bytes, and __LINKEDIT's bytes, unchanged.