mirror of
https://github.com/rui314/mold.git
synced 2026-11-07 09:16:04 -10:00
Call an input section's contents, visit and kill by mold's names
InputSection read its bytes through data(), set its visited bit with mark_visited and was marked dead with set_alive(false). mold's InputSection has contents(), visit() and kill() for these; the methods are named so here too, and the passes that drop a subsection call kill(). set_alive stays for dead stripping, which sets the bit to what its walk found. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
26be971d07
commit
fcd1d6aecc
11 files changed
+48
-41
No files matched your search
@@ -133,7 +133,7 @@ pub fn copy_buf<E: Target>(ctx: &Context<E>, id: OutputSectionId, buf: &mut [u8]
|
||||
// only ever write within their own subsection.
|
||||
for_each_member(ctx, osec, buf, |m, slice| {
|
||||
let isec = &ctx.isecs[m];
|
||||
let data = isec.data();
|
||||
let data = isec.contents();
|
||||
if data.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-5
@@ -163,7 +163,7 @@ fn collect_root_set<E: Target>(
|
||||
// the end.
|
||||
let mut enqueue = |id: usize, root: Root| {
|
||||
let id = redirects[id];
|
||||
if ctx.isecs[id].mark_visited() {
|
||||
if ctx.isecs[id].visit() {
|
||||
roots.push(id);
|
||||
if let Some(why) = why.as_deref_mut() {
|
||||
why[id] = Why::Root(root);
|
||||
@@ -260,7 +260,7 @@ pub fn native_refs_before_lto<E: Target>(
|
||||
for (msym, &id) in obj.mach_syms.iter().zip(&obj.symbols) {
|
||||
if msym.ty() == N_UNDF
|
||||
&& let Some(isec) = ctx.symbols[id].input_section()
|
||||
&& ctx.isecs[redirects[isec as usize]].mark_visited()
|
||||
&& ctx.isecs[redirects[isec as usize]].visit()
|
||||
{
|
||||
roots.push(redirects[isec as usize]);
|
||||
}
|
||||
@@ -370,7 +370,7 @@ fn visit_section<E: Target>(
|
||||
for_each_edge(ctx, id, |target| targets.push(target));
|
||||
for target in targets {
|
||||
let target = redirects[target];
|
||||
if ctx.isecs[target].mark_visited() {
|
||||
if ctx.isecs[target].visit() {
|
||||
if depth < 3 {
|
||||
visit_section(ctx, redirects, target, depth + 1, next);
|
||||
} else {
|
||||
@@ -429,7 +429,7 @@ fn walk<E: Target>(
|
||||
while let Some(id) = queue.pop_front() {
|
||||
for_each_edge(ctx, id, |target| {
|
||||
let target = redirects[target];
|
||||
if ctx.isecs[target].mark_visited() {
|
||||
if ctx.isecs[target].visit() {
|
||||
if let Some(why) = why.as_deref_mut() {
|
||||
why[target] = Why::From(id as u32);
|
||||
}
|
||||
@@ -466,7 +466,7 @@ fn mark_live_support<E: Target>(
|
||||
references_live |= ctx.isecs[redirects[target]].is_visited();
|
||||
});
|
||||
let id = redirects[id];
|
||||
if references_live && ctx.isecs[id].mark_visited() {
|
||||
if references_live && ctx.isecs[id].visit() {
|
||||
if let Some(why) = why.as_deref_mut() {
|
||||
why[id] = Why::Root(Root::LiveSupport);
|
||||
}
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ fn create_delay_helpers<E: Target>(
|
||||
let kind = match how {
|
||||
LazyRef::Cmp => DelayUse::Cmp,
|
||||
LazyRef::Load => {
|
||||
let (reg, own) = E::lazy_load_site(ctx.isecs[isec as usize].data(), offset);
|
||||
let (reg, own) = E::lazy_load_site(ctx.isecs[isec as usize].contents(), offset);
|
||||
DelayUse::Load { reg, site: own.then_some((isec, offset)) }
|
||||
}
|
||||
_ => continue,
|
||||
|
||||
+3
-3
@@ -415,8 +415,8 @@ fn compute_digest<E: Target>(ctx: &Context<E>, cand_index: &[usize], id: usize)
|
||||
let isec = &ctx.isecs[id];
|
||||
let mut h = SipHash13_128::new(&KEY);
|
||||
h.update(&isec.size.to_ne_bytes());
|
||||
h.update(&isec.data().len().to_ne_bytes());
|
||||
h.update(isec.data());
|
||||
h.update(&isec.contents().len().to_ne_bytes());
|
||||
h.update(isec.contents());
|
||||
for rel in isec.rels(&ctx.objs[isec.file as usize]) {
|
||||
h.update(&rel.offset.to_ne_bytes());
|
||||
h.update(&rel.ty.to_ne_bytes());
|
||||
@@ -609,7 +609,7 @@ fn verify_leaders<E: Target>(
|
||||
let equal = |a: usize, b: usize| -> bool {
|
||||
let (x, y) = (&ctx.isecs[a], &ctx.isecs[b]);
|
||||
let (xr, yr) = (x.rels(&ctx.objs[x.file as usize]), y.rels(&ctx.objs[y.file as usize]));
|
||||
x.data() == y.data()
|
||||
x.contents() == y.contents()
|
||||
&& xr.len() == yr.len()
|
||||
&& xr.iter().zip(yr).all(|(r, s)| {
|
||||
r.offset == s.offset
|
||||
|
||||
@@ -231,7 +231,7 @@ pub struct InputSection {
|
||||
/// The subsection contents, as a bare pointer - the length is
|
||||
/// `size` - or 0 when there are none (a zero-fill or empty
|
||||
/// section). Stored as an integer, not a slice, to save 8 bytes and
|
||||
/// keep the struct trivially Send/Sync; read through `data()`.
|
||||
/// keep the struct trivially Send/Sync; read through `contents()`.
|
||||
/// mold likewise keeps `contents` as a bare address.
|
||||
pub contents: usize,
|
||||
/// This subsection's relocations: a range in the owning object's
|
||||
@@ -410,9 +410,14 @@ impl InputSection {
|
||||
*f &= !IS_ALIVE;
|
||||
}
|
||||
}
|
||||
/// Marks the subsection dead.
|
||||
#[inline]
|
||||
pub fn kill(&mut self) {
|
||||
*self.flags.get_mut() &= !IS_ALIVE;
|
||||
}
|
||||
/// Atomically sets the visited bit; true if this call set it.
|
||||
#[inline]
|
||||
pub fn mark_visited(&self) -> bool {
|
||||
pub fn visit(&self) -> bool {
|
||||
self.flags.fetch_or(IS_VISITED, std::sync::atomic::Ordering::Relaxed) & IS_VISITED == 0
|
||||
}
|
||||
/// Clears the visited bit, through a shared reference.
|
||||
@@ -461,7 +466,7 @@ impl InputSection {
|
||||
/// otherwise the `size` bytes at `contents` (which point into the
|
||||
/// mmap'd input, so they live for the whole link).
|
||||
#[inline]
|
||||
pub fn data(&self) -> &'static [u8] {
|
||||
pub fn contents(&self) -> &'static [u8] {
|
||||
if self.contents == 0 {
|
||||
&[]
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -90,7 +90,7 @@ pub(crate) fn import_uses<E: Target>(
|
||||
.filter(|&i| ctx.isecs[i].is_emitted())
|
||||
.flat_map_iter(|i| {
|
||||
let isec = &ctx.isecs[i];
|
||||
let (file, data) = (&ctx.objs[isec.file as usize], isec.data());
|
||||
let (file, data) = (&ctx.objs[isec.file as usize], isec.contents());
|
||||
isec.rels(file).iter().filter_map(move |r| {
|
||||
let id = r.sym(file)?;
|
||||
is_import(id).then(|| (i as u32, r.offset, id, E::lazy_ref(r, data)))
|
||||
@@ -215,7 +215,7 @@ fn create_lazy_helpers<E: Target>(
|
||||
LazyRef::Call => LazyUse::Call,
|
||||
LazyRef::Cmp => LazyUse::Cmp,
|
||||
LazyRef::Load => {
|
||||
let (reg, own) = E::lazy_load_site(ctx.isecs[isec as usize].data(), offset);
|
||||
let (reg, own) = E::lazy_load_site(ctx.isecs[isec as usize].contents(), offset);
|
||||
LazyUse::Load { reg, site: own.then_some((isec, offset)) }
|
||||
}
|
||||
LazyRef::Slot | LazyRef::Unsupported => continue,
|
||||
|
||||
@@ -426,7 +426,7 @@ impl<'a, E: Target> Builder<'a, E> {
|
||||
Content::Image(out.fileoff + isec.offset as u64)
|
||||
}
|
||||
}
|
||||
_ => Content::Pool(isec.data()),
|
||||
_ => Content::Pool(isec.contents()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,7 +639,7 @@ impl<'a, E: Target> Builder<'a, E> {
|
||||
let arm64 = E::CPUTYPE == CPU_TYPE_ARM64;
|
||||
let code = isec.hdr(&ctx.objs[obj]).flags & S_ATTR_SOME_INSTRUCTIONS != 0;
|
||||
let insn = |r: &Reloc| {
|
||||
u32::from_le_bytes(isec.data()[r.offset as usize..][..4].try_into().unwrap())
|
||||
u32::from_le_bytes(isec.contents()[r.offset as usize..][..4].try_into().unwrap())
|
||||
};
|
||||
// The other references to the slot in the subsection, after or
|
||||
// before this one.
|
||||
@@ -774,7 +774,7 @@ impl<'a, E: Target> Builder<'a, E> {
|
||||
continue;
|
||||
}
|
||||
let fixup = if E::CPUTYPE == CPU_TYPE_ARM64 {
|
||||
arm64_fixup(isec.data(), r, target, addend)
|
||||
arm64_fixup(isec.contents(), r, target, addend)
|
||||
} else {
|
||||
x86_64_fixup(hdr, r, target, addend)
|
||||
};
|
||||
|
||||
+13
-13
@@ -285,7 +285,7 @@ fn objc_class_ro<E: Target>(ctx: &Context<E>, cls: (u32, u64)) -> Option<(u32, u
|
||||
/// The C string a reference points at, if it is in the image.
|
||||
fn objc_cstring_at<E: Target>(ctx: &Context<E>, r: Option<ObjcRef>) -> Option<&'static [u8]> {
|
||||
let (isec, off) = objc_ref_location(ctx, r?)?;
|
||||
let data = ctx.isecs[isec as usize].data();
|
||||
let data = ctx.isecs[isec as usize].contents();
|
||||
let bytes = data.get(off as usize..)?;
|
||||
let end = bytes.iter().position(|&b| b == 0)?;
|
||||
Some(&bytes[..end])
|
||||
@@ -427,7 +427,7 @@ fn ref_key<E: Target>(ctx: &Context<E>, i: usize) -> Option<RefKey> {
|
||||
targets.sort_by_key(|t| t.0);
|
||||
// The relocated fields hold per-object addends (x86-64
|
||||
// embeds the target's address); the targets stand for them.
|
||||
let mut bytes = isec.data().to_vec();
|
||||
let mut bytes = isec.contents().to_vec();
|
||||
for rel in rels {
|
||||
let (a, b) = (rel.offset as usize, rel.offset as usize + rel.size as usize);
|
||||
bytes[a..b].fill(0);
|
||||
@@ -581,7 +581,7 @@ pub fn fold_objc_classrefs<E: Target>(ctx: &mut Context<E>) {
|
||||
// A pair's halves go together, as its offset half decides.
|
||||
let mut keep = hashbrown::HashSet::new();
|
||||
for u in &uses[obj_idx] {
|
||||
let data = ctx.isecs[u.isec as usize].data();
|
||||
let data = ctx.isecs[u.isec as usize].contents();
|
||||
let relocs = &ctx.objs[obj_idx].relocs;
|
||||
let decider = offset_half[obj_idx].get(&u.k).copied().unwrap_or(u.k);
|
||||
let (rel, decider) = (relocs[u.k], relocs[decider]);
|
||||
@@ -621,7 +621,7 @@ pub fn fold_objc_classrefs<E: Target>(ctx: &mut Context<E>) {
|
||||
ctx.symbols[class].add_flags(NEEDS_GOT);
|
||||
kept.push((slot, class));
|
||||
} else {
|
||||
ctx.isecs[slot as usize].set_alive(false);
|
||||
ctx.isecs[slot as usize].kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1030,7 +1030,7 @@ fn classic_list_header(data: &[u8]) -> Option<(u32, u64)> {
|
||||
fn classic_methods<E: Target>(ctx: &Context<E>, list: u32) -> Option<Vec<(u32, ObjcRef, ObjcRef)>> {
|
||||
// Not in the relative form already (the top flag), and 24 bytes an
|
||||
// entry.
|
||||
let (entsize_flags, count) = classic_list_header(ctx.isecs[list as usize].data())?;
|
||||
let (entsize_flags, count) = classic_list_header(ctx.isecs[list as usize].contents())?;
|
||||
if entsize_flags & 0x8000_0000 != 0 || entsize_flags & 0xffff != 24 {
|
||||
return None;
|
||||
}
|
||||
@@ -1112,7 +1112,7 @@ pub fn merge_objc_categories<E: Target>(ctx: &mut Context<E>) {
|
||||
retarget_class_data(ctx, class.meta, meta_ro);
|
||||
|
||||
for &ci in &class.cats {
|
||||
ctx.isecs[cats[ci].isec as usize].set_alive(false);
|
||||
ctx.isecs[cats[ci].isec as usize].kill();
|
||||
cats[ci].merged = true;
|
||||
}
|
||||
if !class.nonlazy && class.cats.iter().any(|&ci| cats[ci].nonlazy) {
|
||||
@@ -1398,7 +1398,7 @@ fn read_method_list<E: Target>(
|
||||
if relative {
|
||||
return None;
|
||||
}
|
||||
let (entsize_flags, count) = classic_list_header(ctx.isecs[isec as usize].data())?;
|
||||
let (entsize_flags, count) = classic_list_header(ctx.isecs[isec as usize].contents())?;
|
||||
if entsize_flags != 24 {
|
||||
return None;
|
||||
}
|
||||
@@ -1419,7 +1419,7 @@ fn read_method_list<E: Target>(
|
||||
fn read_protocol_list<E: Target>(ctx: &Context<E>, list: Option<ObjcRef>) -> Option<Vec<ObjcRef>> {
|
||||
let Some(r) = list else { return Some(Vec::new()) };
|
||||
let (isec, off) = objc_ref_location(ctx, r)?;
|
||||
let data = ctx.isecs[isec as usize].data();
|
||||
let data = ctx.isecs[isec as usize].contents();
|
||||
let count = u64::from_le_bytes(data.get(off as usize..off as usize + 8)?.try_into().unwrap());
|
||||
(0..count).map(|i| objc_pointer_at(ctx, isec, off + 8 + 8 * i)).collect()
|
||||
}
|
||||
@@ -1432,7 +1432,7 @@ fn read_property_list<E: Target>(
|
||||
) -> Option<Vec<(ObjcRef, ObjcRef)>> {
|
||||
let Some(r) = list else { return Some(Vec::new()) };
|
||||
let (isec, off) = objc_ref_location(ctx, r)?;
|
||||
let data = ctx.isecs[isec as usize].data();
|
||||
let data = ctx.isecs[isec as usize].contents();
|
||||
let entsize = u32::from_le_bytes(data.get(off as usize..off as usize + 4)?.try_into().unwrap());
|
||||
let count =
|
||||
u32::from_le_bytes(data.get(off as usize + 4..off as usize + 8)?.try_into().unwrap())
|
||||
@@ -1615,7 +1615,7 @@ fn drop_superseded_lists<E: Target>(
|
||||
|
||||
fn drop_list<E: Target>(ctx: &mut Context<E>, list: Option<ObjcRef>) {
|
||||
if let Some((isec, 0)) = list.and_then(|r| objc_ref_location(ctx, r)) {
|
||||
ctx.isecs[isec as usize].set_alive(false);
|
||||
ctx.isecs[isec as usize].kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1635,7 +1635,7 @@ fn rewrite_ro<E: Target>(
|
||||
protocols: Option<ObjcRef>,
|
||||
props: Option<ObjcRef>,
|
||||
) -> u32 {
|
||||
let data = ctx.isecs[ro.0 as usize].data()[ro.1 as usize..ro.1 as usize + 16].to_vec();
|
||||
let data = ctx.isecs[ro.0 as usize].contents()[ro.1 as usize..ro.1 as usize + 16].to_vec();
|
||||
let flags = u32::from_le_bytes(data[0..4].try_into().unwrap());
|
||||
let len = if flags & (1 << 6) != 0 { 80 } else { 72 };
|
||||
let mut fields = vec![DataField::Bytes(data)];
|
||||
@@ -1664,7 +1664,7 @@ fn rewrite_ro<E: Target>(
|
||||
// The record was a subsection of its own: replace it, so its
|
||||
// symbol names the new record too (ld64 keeps
|
||||
// __OBJC_CLASS_RO_$_Foo).
|
||||
isec.set_alive(false);
|
||||
isec.kill();
|
||||
isec.replacement = blob;
|
||||
}
|
||||
blob
|
||||
@@ -1701,7 +1701,7 @@ fn rebuild_category_lists<E: Target>(
|
||||
if !list.entries.iter().any(|&(_, ci)| merged(ci)) {
|
||||
continue;
|
||||
}
|
||||
ctx.isecs[list.isec as usize].set_alive(false);
|
||||
ctx.isecs[list.isec as usize].kill();
|
||||
let survivors: Vec<DataField> = (list.entries.iter())
|
||||
.filter(|&&(_, ci)| !merged(ci))
|
||||
.map(|&(r, _)| DataField::Ptr(r))
|
||||
|
||||
@@ -803,7 +803,7 @@ fn group_input_sections<E: Target>(
|
||||
};
|
||||
let Some(group) = group else {
|
||||
// Consumed by the link: no output section.
|
||||
isec.set_alive(false);
|
||||
isec.kill();
|
||||
continue;
|
||||
};
|
||||
let group = &mut groups[group].1;
|
||||
|
||||
+6
-6
@@ -972,7 +972,7 @@ fn retire_bitcode_placeholders<E: Target>(ctx: &mut Context<E>) {
|
||||
pub fn remove_unreachable_files<E: Target>(ctx: &mut Context<E>) {
|
||||
for isec in ctx.isecs.iter_mut() {
|
||||
if !ctx.objs[isec.file as usize].is_alive {
|
||||
isec.set_alive(false);
|
||||
isec.kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,7 +996,7 @@ pub fn remove_swift_reflection_metadata<E: Target>(ctx: &mut Context<E>) {
|
||||
})
|
||||
.collect();
|
||||
for i in removed {
|
||||
ctx.isecs[i].set_alive(false);
|
||||
ctx.isecs[i].kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1074,7 +1074,7 @@ pub fn convert_init_offsets<E: Target>(ctx: &mut Context<E>) {
|
||||
};
|
||||
ctx.init_offsets.init_funcs.push(func);
|
||||
}
|
||||
ctx.isecs[i].set_alive(false);
|
||||
ctx.isecs[i].kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1287,7 +1287,7 @@ pub fn merge_literals<E: Target>(ctx: &mut Context<E>) {
|
||||
if !input_files::is_mergeable_literal(hdr, isec) {
|
||||
return None;
|
||||
}
|
||||
Some((xxhash_rust::xxh3::xxh3_64(isec.data()), hdr, i as u32))
|
||||
Some((xxhash_rust::xxh3::xxh3_64(isec.contents()), hdr, i as u32))
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1324,13 +1324,13 @@ fn merge_shard(isecs: &[InputSection], shard: Vec<Literal>) -> Vec<(u32, u32)> {
|
||||
let mut losers: Vec<(u32, u32)> = Vec::new();
|
||||
let p2align = |i: u32| isecs[i as usize].p2align_at(isecs[i as usize].input_addr as u64);
|
||||
for (hash, hdr, i) in shard {
|
||||
let data = isecs[i as usize].data();
|
||||
let data = isecs[i as usize].contents();
|
||||
let same = |&(h, other, j, _): &(u64, &MachSection, u32, u32)| {
|
||||
h == hash
|
||||
&& other.segname == hdr.segname
|
||||
&& other.sectname == hdr.sectname
|
||||
&& other.section_type() == hdr.section_type()
|
||||
&& isecs[j as usize].data() == data
|
||||
&& isecs[j as usize].contents() == data
|
||||
};
|
||||
match table.entry(hash, same, |e| e.0) {
|
||||
hashbrown::hash_table::Entry::Occupied(e) => {
|
||||
|
||||
@@ -975,19 +975,21 @@ fn copy_section_contents<E: Target>(
|
||||
let osec = ctx.output_section(osec);
|
||||
if !osec.hdr.is_zerofill() {
|
||||
let isecs = osec.members.iter().map(|&id| &ctx.isecs[id]);
|
||||
jobs.extend(isecs.filter(|isec| !isec.data().is_empty()).map(|isec| (&osec.hdr, isec)));
|
||||
jobs.extend(
|
||||
isecs.filter(|isec| !isec.contents().is_empty()).map(|isec| (&osec.hdr, isec)),
|
||||
);
|
||||
}
|
||||
}
|
||||
let ranges: Vec<std::ops::Range<u64>> = jobs
|
||||
.iter()
|
||||
.map(|&(hdr, isec)| {
|
||||
let start = hdr.fileoff + isec.offset as u64;
|
||||
start..start + isec.data().len() as u64
|
||||
start..start + isec.contents().len() as u64
|
||||
})
|
||||
.collect();
|
||||
let slices = output_file::split_ranges(buf, &ranges);
|
||||
jobs.into_par_iter().zip(slices).for_each(|((hdr, isec), out)| {
|
||||
out.copy_from_slice(isec.data());
|
||||
out.copy_from_slice(isec.contents());
|
||||
for rel in isec.rels(&ctx.objs[isec.file as usize]) {
|
||||
let here = hdr.addr + isec.offset as u64 + rel.offset as u64;
|
||||
rewrite_field(targets, isec, rel, here, &mut out[rel.offset as usize..]);
|
||||
|
||||
Reference in new issue
Block a user