mirror of
https://github.com/rui314/mold.git
synced 2026-11-09 04:49:33 -10:00
Merge pull request #25 from bitemyapp/parity/21-umbrella-noreloc
Order the umbrella commands and flag an anchors-only segment as ld-prime does
This commit is contained in:
5 files changed
+42
-6
No files matched your search
+31
-6
@@ -327,6 +327,26 @@ fn create_segment_cmd<E: Target>(ctx: &Context<E>, seg: &OutputSegment) -> Vec<u
|
||||
if seg.name == "__DATA_CONST" {
|
||||
cmd.flags = SG_READ_ONLY;
|
||||
}
|
||||
// A segment of nothing but -add_empty_section anchors has nothing
|
||||
// to relocate; ld-prime flags it SG_NORELOC. Only that option, not
|
||||
// an empty section a `section$start$` boundary symbol conjured, and
|
||||
// not an empty segment such as __PAGEZERO (no sections at all).
|
||||
if !seg.chunks.is_empty()
|
||||
&& seg.chunks.iter().all(|&id| match id {
|
||||
ChunkId::SectCreate(i) => {
|
||||
let h = &ctx.sectcreate_sections[i as usize].hdr;
|
||||
h.size == 0
|
||||
&& ctx
|
||||
.args
|
||||
.add_empty_section
|
||||
.iter()
|
||||
.any(|(seg, sect)| seg == h.segname && sect == &h.sectname)
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
cmd.flags |= SG_NORELOC;
|
||||
}
|
||||
|
||||
let mut buf = to_vec(&cmd);
|
||||
for hdr in sects {
|
||||
@@ -569,12 +589,6 @@ pub fn create_load_commands<E: Target>(ctx: &Context<E>) -> Vec<Vec<u8>> {
|
||||
|
||||
if ctx.args.output_type == MH_DYLIB {
|
||||
vec.push(create_id_dylib_cmd(ctx));
|
||||
if let Some(name) = &ctx.args.umbrella {
|
||||
vec.push(create_string_cmd(LC_SUB_FRAMEWORK, name));
|
||||
}
|
||||
for client in &ctx.args.allowable_clients {
|
||||
vec.push(create_string_cmd(LC_SUB_CLIENT, client));
|
||||
}
|
||||
}
|
||||
|
||||
// Chained fixups replace the classic dyld info; the export trie
|
||||
@@ -608,6 +622,17 @@ pub fn create_load_commands<E: Target>(ctx: &Context<E>) -> Vec<Vec<u8>> {
|
||||
vec.push(create_load_dylib_cmd(dylib));
|
||||
}
|
||||
|
||||
// The umbrella commands follow the libraries, clients first, as
|
||||
// ld-prime orders them.
|
||||
if ctx.args.output_type == MH_DYLIB {
|
||||
for client in &ctx.args.allowable_clients {
|
||||
vec.push(create_string_cmd(LC_SUB_CLIENT, client));
|
||||
}
|
||||
if let Some(name) = &ctx.args.umbrella {
|
||||
vec.push(create_string_cmd(LC_SUB_FRAMEWORK, name));
|
||||
}
|
||||
}
|
||||
|
||||
for rpath in &ctx.args.rpaths {
|
||||
vec.push(create_string_cmd(LC_RPATH, rpath));
|
||||
}
|
||||
|
||||
@@ -200,6 +200,7 @@ pub const BIND_SPECIAL_DYLIB_WEAK_LOOKUP: i32 = -3;
|
||||
pub const BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: u8 = 0x30;
|
||||
|
||||
// Segment flags
|
||||
pub const SG_NORELOC: u32 = 0x4;
|
||||
pub const SG_READ_ONLY: u32 = 0x10;
|
||||
|
||||
// Bind opcodes, for the LC_DYLD_INFO bind stream. Each opcode byte holds
|
||||
|
||||
@@ -9,3 +9,6 @@ $CC --ld-path=$mold -o $t/exe $t/a.o -Wl,-add_empty_section,__FOO,__foo
|
||||
|
||||
otool -l $t/exe | grep 'segname __FOO'
|
||||
otool -l $t/exe | grep 'sectname __foo'
|
||||
# The segment of only such anchors is flagged SG_NORELOC, as ld-prime
|
||||
# flags it.
|
||||
otool -l $t/exe | grep -A9 'segname __FOO' | grep 'flags 0x4'
|
||||
@@ -14,6 +14,8 @@ EOF
|
||||
$CC --ld-path=$mold -shared -o $t/libsub.dylib $t/a.o \
|
||||
-Wl,-umbrella,Big -Wl,-allowable_client,friend
|
||||
otool -l $t/libsub.dylib | grep 'client friend'
|
||||
# The umbrella commands follow the libraries, clients first (ld-prime).
|
||||
[ "$(otool -l $t/libsub.dylib | grep '^ *cmd ' | awk '{print $2}' | grep -E 'LC_LOAD_DYLIB|LC_SUB' | uniq | tr '\n' ' ')" = "LC_LOAD_DYLIB LC_SUB_CLIENT LC_SUB_FRAMEWORK " ]
|
||||
|
||||
# A random client is rejected.
|
||||
not $CC --ld-path=$mold -o $t/exe $t/b.o $t/libsub.dylib 2> $t/log
|
||||
|
||||
@@ -24,3 +24,8 @@ EOF
|
||||
|
||||
$CC --ld-path=$mold -o $t/exe $t/a.o
|
||||
$t/exe > /dev/null
|
||||
# A __FOO segment conjured by a section$start boundary symbol is not an
|
||||
# -add_empty_section anchor: its segment carries no SG_NORELOC (0x0),
|
||||
# as ld-prime writes it.
|
||||
otool -l $t/exe > $t/lc
|
||||
[ "$(awk '/segname __FOO/{g=1} g&&/^ *flags/{print $2; exit}' $t/lc)" = 0x0 ]
|
||||
Reference in new issue
Block a user