Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions libwild/MachO.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ Contents of __unwind_info section:
## `LC_CODE_SIGNATURE` command

Code signature is mandatory and cannot run a final binary without it. Can be manually created for a produced binary: `codesign -s - -f a.out`.
A linker can skip emitting the signature by using: `-Wl,-no_adhoc_codesign`.
A linker can skip emitting the signature by using: `-Wl,-no_adhoc_codesign`. One drawback of invoking `codesign` externally is that you
must reserve space for the additional load command in advance; otherwise, offsets in segments such as `__TEXT` will shift.

It's basically an array of SHA-256 hashes, one for each page of the file - similar to how we emit build-id. There's existing LLVM implementation
of the format we can use: https://github.com/llvm/llvm-project/blob/36e495dd903cea000f6c4f51954554c22f39d7da/lld/MachO/SyntheticSections.cpp#L1622-L1662

Expand All @@ -196,9 +198,17 @@ Pretty straightforward to implement, replaces a legacy `LC_DYLD_INFO(_ONLY)` com

## `LC_DYLD_CHAINED_FIXUPS` command

TODO: explain better
This is roughly analogous to dynamic relocations in ELF. The format is made up of three parts:

- a table of imported symbols, including the symbol name and the referenced dylib
- a string table used by the import table
- a per-segment chain of fixups, where each entry records the location to patch and an index into the import table that identifies the target

Good documentation is available here: https://github.com/qyang-nj/llios/blob/main/dynamic_linking/chained_fixups.md.
The relevant data structures are also defined in Apple's `mach-o/fixup-chains.h` header
and mirrored here: https://github.com/qyang-nj/llios/blob/d204d56ff0533c1fae115b77e7554d2e6f4bc4aa/apple_open_source/dyld/include/mach-o/fixup-chains.h.

Good documentation here: https://github.com/qyang-nj/llios/blob/main/dynamic_linking/chained_fixups.md.
Ideally, support for these structures should be added to the `object` crate.

## benchmarks: LLD vs. system linker

Expand Down
3 changes: 3 additions & 0 deletions libwild/src/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ pub(crate) const NOTE_GNU_BUILD_ID: Alignment = Alignment { exponent: 2 };
// GNU_STACK.alignment
pub(crate) const STACK_ALIGNMENT: Alignment = Alignment { exponent: 4 };

// Mach-O specific
pub(crate) const MACHO_PAGE_ALIGNMENT: Alignment = Alignment { exponent: 14 };

impl Alignment {
pub(crate) fn new(raw: u64) -> Result<Self> {
if !raw.is_power_of_two() {
Expand Down
4 changes: 3 additions & 1 deletion libwild/src/args/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#![allow(unused_variables)]
#![allow(unused)]

use crate::alignment::Alignment;
use crate::alignment::MACHO_PAGE_ALIGNMENT;
use crate::args::ArgumentParser;
use crate::args::CommonArgs;
use crate::args::FILES_PER_GROUP_ENV;
Expand Down Expand Up @@ -92,7 +94,7 @@ impl platform::Args for MachOArgs {
}

fn loadable_segment_alignment(&self) -> crate::alignment::Alignment {
todo!()
MACHO_PAGE_ALIGNMENT
}

fn should_merge_sections(&self) -> bool {
Expand Down
9 changes: 9 additions & 0 deletions libwild/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,15 @@ impl platform::Platform for Elf {
group_sizes.merge(&extra_sizes);
total_sizes.merge(&extra_sizes);
}

fn align_load_segment_start(
_segment_def: Self::ProgramSegmentDef,
segment_alignment: Alignment,
file_offset: &mut usize,
mem_offset: &mut u64,
) {
*mem_offset = segment_alignment.align_modulo(*file_offset as u64, *mem_offset);
}
}

impl<'data> platform::ObjectFile<'data> for File<'data> {
Expand Down
9 changes: 8 additions & 1 deletion libwild/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4591,11 +4591,18 @@ fn layout_section_parts<P: Platform>(
.copied()
.unwrap_or_else(|| args.loadable_segment_alignment());
if let Some(location) = pending_location.take() {
// The OrderEvent::SetLocation is ELF-specific only.
mem_offset = location.address;
file_offset =
segment_alignment.align_modulo(mem_offset, file_offset as u64) as usize;
} else {
mem_offset = segment_alignment.align_modulo(file_offset as u64, mem_offset);
let segment_def = *program_segments.segment_def(segment_id);
P::align_load_segment_start(
segment_def,
segment_alignment,
&mut file_offset,
&mut mem_offset,
);
}
}
}
Expand Down
Loading
Loading