mirror of
https://github.com/rui314/mold.git
synced 2026-11-09 13:01:26 -10:00
Collapse nested ifs into let chains
This commit is contained in:
1 parent
61c0854ddc
commit
ebbda8f4bc
19 files changed
+280
-287
No files matched your search
@@ -43,17 +43,15 @@ fn git_hash(source_dir: &Path) -> Option<String> {
|
||||
let reftable = git_path("reftable/tables.list").filter(|p| p.exists());
|
||||
if let Some(head) = git_path("HEAD").filter(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", head.display());
|
||||
if let Ok(contents) = std::fs::read_to_string(&head) {
|
||||
if let Some(reference) =
|
||||
if let Ok(contents) = std::fs::read_to_string(&head)
|
||||
&& let Some(reference) =
|
||||
contents.strip_prefix("ref: ").map(str::trim).filter(|_| reftable.is_none())
|
||||
{
|
||||
if let Some(path) = git_path(reference) {
|
||||
// A packed reference may acquire a loose file later.
|
||||
// Watch its nearest existing directory until that happens.
|
||||
if let Some(path) = path.ancestors().find(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
&& let Some(path) = git_path(reference)
|
||||
{
|
||||
// A packed reference may acquire a loose file later.
|
||||
// Watch its nearest existing directory until that happens.
|
||||
if let Some(path) = path.ancestors().find(|p| p.exists()) {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +67,11 @@ pub fn copy_buf<E: Arch>(ctx: &Context<E>, buf: &mut [u8], eh_frame_buf: Option<
|
||||
rel.set_r_sym(r_sym);
|
||||
if E::IS_RELA {
|
||||
rel.set_r_addend(addend);
|
||||
} else if ctx.args.relocatable && is_section {
|
||||
if let Some(eh) = eh_frame_buf {
|
||||
E::write_addend(&mut eh[offset as usize..], addend, r);
|
||||
}
|
||||
} else if ctx.args.relocatable
|
||||
&& is_section
|
||||
&& let Some(eh) = eh_frame_buf
|
||||
{
|
||||
E::write_addend(&mut eh[offset as usize..], addend, r);
|
||||
}
|
||||
out[n] = rel;
|
||||
n += 1;
|
||||
|
||||
+9
-9
@@ -149,16 +149,16 @@ fn for_each_entry<E: Arch>(ctx: &Context<E>, mut emit: impl FnMut(GotEntry)) {
|
||||
let idx = sym.got_idx(&ctx.symbols).unwrap();
|
||||
|
||||
// IFUNC always needs to be fixed up by the dynamic linker.
|
||||
if let Some(r_irelative) = E::R_IRELATIVE {
|
||||
if sym.is_ifunc() {
|
||||
if sym.is_pde_ifunc(ctx) {
|
||||
add(idx, sym.plt_addr(ctx), R_NONE, None);
|
||||
add(idx + 1, sym.addr_with(ctx, AddrFlags::NO_PLT), r_irelative, None);
|
||||
} else {
|
||||
add(idx, sym.addr_with(ctx, AddrFlags::NO_PLT), r_irelative, None);
|
||||
}
|
||||
continue;
|
||||
if let Some(r_irelative) = E::R_IRELATIVE
|
||||
&& sym.is_ifunc()
|
||||
{
|
||||
if sym.is_pde_ifunc(ctx) {
|
||||
add(idx, sym.plt_addr(ctx), R_NONE, None);
|
||||
add(idx + 1, sym.addr_with(ctx, AddrFlags::NO_PLT), r_irelative, None);
|
||||
} else {
|
||||
add(idx, sym.addr_with(ctx, AddrFlags::NO_PLT), r_irelative, None);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if sym.is_imported() {
|
||||
|
||||
+36
-36
@@ -322,10 +322,10 @@ fn write_shdr<E: Arch>(ctx: &Context<E>, buf: &mut [u8]) {
|
||||
buf.fill(0);
|
||||
|
||||
let mut first = ElfShdr::<E>::default();
|
||||
if let Some(shstrtab) = &ctx.shstrtab {
|
||||
if shstrtab.shndx >= SHN_LORESERVE {
|
||||
first.sh_link.set(shstrtab.shndx);
|
||||
}
|
||||
if let Some(shstrtab) = &ctx.shstrtab
|
||||
&& shstrtab.shndx >= SHN_LORESERVE
|
||||
{
|
||||
first.sh_link.set(shstrtab.shndx);
|
||||
}
|
||||
let shnum = buf.len() / size;
|
||||
if shnum > u16::MAX as usize {
|
||||
@@ -427,10 +427,10 @@ fn create_phdr<E: Arch>(ctx: &Context<E>) -> Vec<ElfPhdr<E>> {
|
||||
chunks.sort_by_key(|&id| ctx.chunk_header(id).shdr.sh_addr.get());
|
||||
|
||||
// Create a PT_PHDR for the program header itself.
|
||||
if let Some(phdr) = &ctx.phdr {
|
||||
if phdr.hdr.is_alloc() {
|
||||
define(&mut vec, PT_PHDR, PF_R, &phdr.hdr.shdr);
|
||||
}
|
||||
if let Some(phdr) = &ctx.phdr
|
||||
&& phdr.hdr.is_alloc()
|
||||
{
|
||||
define(&mut vec, PT_PHDR, PF_R, &phdr.hdr.shdr);
|
||||
}
|
||||
|
||||
// Create a PT_INTERP.
|
||||
@@ -507,11 +507,11 @@ fn create_phdr<E: Arch>(ctx: &Context<E>) -> Vec<ElfPhdr<E>> {
|
||||
}
|
||||
|
||||
// Add PT_DYNAMIC
|
||||
if let Some(osec) = &ctx.dynamic {
|
||||
if osec.shdr.sh_size.get() != 0 {
|
||||
let flags = to_phdr_flags(ctx, ChunkId::Dynamic);
|
||||
define(&mut vec, PT_DYNAMIC, flags, &osec.shdr);
|
||||
}
|
||||
if let Some(osec) = &ctx.dynamic
|
||||
&& osec.shdr.sh_size.get() != 0
|
||||
{
|
||||
let flags = to_phdr_flags(ctx, ChunkId::Dynamic);
|
||||
define(&mut vec, PT_DYNAMIC, flags, &osec.shdr);
|
||||
}
|
||||
|
||||
// Add PT_GNU_EH_FRAME
|
||||
@@ -530,10 +530,10 @@ fn create_phdr<E: Arch>(ctx: &Context<E>) -> Vec<ElfPhdr<E>> {
|
||||
}
|
||||
|
||||
// Create a PT_RISCV_ATTRIBUTES
|
||||
if let Some(osec) = &ctx.riscv_attributes {
|
||||
if osec.hdr.shdr.sh_size.get() != 0 {
|
||||
define(&mut vec, PT_RISCV_ATTRIBUTES, PF_R, &osec.hdr.shdr);
|
||||
}
|
||||
if let Some(osec) = &ctx.riscv_attributes
|
||||
&& osec.hdr.shdr.sh_size.get() != 0
|
||||
{
|
||||
define(&mut vec, PT_RISCV_ATTRIBUTES, PF_R, &osec.hdr.shdr);
|
||||
}
|
||||
|
||||
// Create a PT_ARM_EDXIDX
|
||||
@@ -596,26 +596,26 @@ fn create_phdr<E: Arch>(ctx: &Context<E>) -> Vec<ElfPhdr<E>> {
|
||||
// that they can be directly read/executed from ROM. If a gap between
|
||||
// two segments is two page size or larger, we give up and pack segments
|
||||
// tightly so that we don't waste too much ROM area.
|
||||
if let Some(base) = ctx.args.physical_image_base {
|
||||
if let Some(first) = vec.iter().position(|p| p.p_type().get() == PT_LOAD) {
|
||||
let mut addr = base;
|
||||
let mut in_sync = vec[first].p_vaddr().get() == addr;
|
||||
vec[first].p_paddr_mut().set(addr);
|
||||
addr += vec[first].p_memsz().get();
|
||||
if let Some(base) = ctx.args.physical_image_base
|
||||
&& let Some(first) = vec.iter().position(|p| p.p_type().get() == PT_LOAD)
|
||||
{
|
||||
let mut addr = base;
|
||||
let mut in_sync = vec[first].p_vaddr().get() == addr;
|
||||
vec[first].p_paddr_mut().set(addr);
|
||||
addr += vec[first].p_memsz().get();
|
||||
|
||||
for p in vec[first + 1..].iter_mut().take_while(|p| p.p_type().get() == PT_LOAD) {
|
||||
if in_sync
|
||||
&& addr <= p.p_vaddr().get()
|
||||
&& p.p_vaddr().get() < addr + ctx.args.page_size * 2
|
||||
{
|
||||
let vaddr = p.p_vaddr().get();
|
||||
p.p_paddr_mut().set(vaddr);
|
||||
addr = vaddr + p.p_memsz().get();
|
||||
} else {
|
||||
in_sync = false;
|
||||
p.p_paddr_mut().set(addr);
|
||||
addr += p.p_memsz().get();
|
||||
}
|
||||
for p in vec[first + 1..].iter_mut().take_while(|p| p.p_type().get() == PT_LOAD) {
|
||||
if in_sync
|
||||
&& addr <= p.p_vaddr().get()
|
||||
&& p.p_vaddr().get() < addr + ctx.args.page_size * 2
|
||||
{
|
||||
let vaddr = p.p_vaddr().get();
|
||||
p.p_paddr_mut().set(vaddr);
|
||||
addr = vaddr + p.p_memsz().get();
|
||||
} else {
|
||||
in_sync = false;
|
||||
p.p_paddr_mut().set(addr);
|
||||
addr += p.p_memsz().get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-28
@@ -83,11 +83,11 @@ fn symidx_addend<'a, E: Arch>(
|
||||
let file = &ctx.objs[isec.file.index()];
|
||||
let sym = &ctx.symbols[file.base.symbols[rel.r_sym() as usize]];
|
||||
|
||||
if !isec.is_alloc() {
|
||||
if let Some((frag, addend)) = isec.fragment(ctx, rel, cache) {
|
||||
let msec = &ctx.merged_sections[frag.section.index()];
|
||||
return (msec.hdr.shndx, msec.fragments.get(frag.entry).offset() as i64 + addend);
|
||||
}
|
||||
if !isec.is_alloc()
|
||||
&& let Some((frag, addend)) = isec.fragment(ctx, rel, cache)
|
||||
{
|
||||
let msec = &ctx.merged_sections[frag.section.index()];
|
||||
return (msec.hdr.shndx, msec.fragments.get(frag.entry).offset() as i64 + addend);
|
||||
}
|
||||
|
||||
if sym.st_type() == STT_SECTION {
|
||||
@@ -107,24 +107,6 @@ fn symidx_addend<'a, E: Arch>(
|
||||
output_symidx_addend(ctx, sym, || isec.rel_addend(rel)).unwrap_or((0, 0))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::arch::I386;
|
||||
use crate::cmdline::Args;
|
||||
|
||||
#[test]
|
||||
fn discarded_section_does_not_read_implicit_addend() {
|
||||
let ctx = Context::<I386>::new(Args::default(), Vec::new());
|
||||
let mut sym = Symbol::new(BStr::new(b".text"));
|
||||
let mut esym = ElfSym::<I386>::default();
|
||||
esym.set_type(STT_SECTION);
|
||||
sym.set_esym(&esym);
|
||||
|
||||
assert_eq!(output_symidx_addend(&ctx, &sym, || panic!("read discarded relocation")), None);
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the relocations. With `-r` on a REL target, the addends are
|
||||
/// written into the output section's bytes, passed as `osec_buf`.
|
||||
pub fn copy_buf<E: Arch>(ctx: &Context<E>, i: u32, buf: &mut [u8], osec_buf: Option<&mut [u8]>) {
|
||||
@@ -154,12 +136,30 @@ pub fn copy_buf<E: Arch>(ctx: &Context<E>, i: u32, buf: &mut [u8], osec_buf: Opt
|
||||
let out_addend = if E::FAMILY == crate::arch::Family::Sh4 { 0 } else { addend };
|
||||
out[base + j] = ElfRel::<E>::new(r_offset, rel.r_type(), symidx, out_addend);
|
||||
|
||||
if ctx.args.relocatable {
|
||||
if let Some(osec_buf) = osec_buf.as_deref_mut() {
|
||||
let loc = (isec.offset() + rel.r_offset()) as usize;
|
||||
E::write_addend(&mut osec_buf[loc..], addend, rel);
|
||||
}
|
||||
if ctx.args.relocatable
|
||||
&& let Some(osec_buf) = osec_buf.as_deref_mut()
|
||||
{
|
||||
let loc = (isec.offset() + rel.r_offset()) as usize;
|
||||
E::write_addend(&mut osec_buf[loc..], addend, rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::arch::I386;
|
||||
use crate::cmdline::Args;
|
||||
|
||||
#[test]
|
||||
fn discarded_section_does_not_read_implicit_addend() {
|
||||
let ctx = Context::<I386>::new(Args::default(), Vec::new());
|
||||
let mut sym = Symbol::new(BStr::new(b".text"));
|
||||
let mut esym = ElfSym::<I386>::default();
|
||||
esym.set_type(STT_SECTION);
|
||||
sym.set_esym(&esym);
|
||||
|
||||
assert_eq!(output_symidx_addend(&ctx, &sym, || panic!("read discarded relocation")), None);
|
||||
}
|
||||
}
|
||||
@@ -199,15 +199,15 @@ fn carve<'a>(rest: &mut &'a mut [u8], pos: &mut usize, start: usize, len: usize)
|
||||
// size as well.
|
||||
fn symbol_size<E: Arch>(ctx: &Context<E>, sym: &Symbol) -> u64 {
|
||||
let esym = &sym.esym(ctx);
|
||||
if (E::IS_RISCV || E::IS_LOONGARCH) && esym.st_size().get() != 0 {
|
||||
if let Some(isec) = sym.input_section_ref(ctx) {
|
||||
if isec.sh_flags & SHF_EXECINSTR as u64 != 0 {
|
||||
let end = esym.st_value().get() + esym.st_size().get();
|
||||
return (esym.st_size().get() as i64 + esym.st_value().get() as i64
|
||||
- sym.value as i64
|
||||
- r_delta(isec, end)) as u64;
|
||||
}
|
||||
}
|
||||
if (E::IS_RISCV || E::IS_LOONGARCH)
|
||||
&& esym.st_size().get() != 0
|
||||
&& let Some(isec) = sym.input_section_ref(ctx)
|
||||
&& isec.sh_flags & SHF_EXECINSTR as u64 != 0
|
||||
{
|
||||
let end = esym.st_value().get() + esym.st_size().get();
|
||||
return (esym.st_size().get() as i64 + esym.st_value().get() as i64
|
||||
- sym.value as i64
|
||||
- r_delta(isec, end)) as u64;
|
||||
}
|
||||
esym.st_size().get()
|
||||
}
|
||||
|
||||
+4
-4
@@ -1933,10 +1933,10 @@ pub fn parse_args(target: &TargetTraits, raw_cmdline: &[Cow<'_, OsStr>]) -> Pars
|
||||
parse_report_output(path.as_os_str()).unwrap_or(ReportOutput::Stdout)
|
||||
});
|
||||
|
||||
if !directory.as_os_str().is_empty() {
|
||||
if let Err(e) = std::env::set_current_dir(&directory) {
|
||||
fatal!("chdir failed: {}: {e}", directory.display());
|
||||
}
|
||||
if !directory.as_os_str().is_empty()
|
||||
&& let Err(e) = std::env::set_current_dir(&directory)
|
||||
{
|
||||
fatal!("chdir failed: {}: {e}", directory.display());
|
||||
}
|
||||
|
||||
if !a.sysroot.as_os_str().is_empty() {
|
||||
|
||||
+12
-12
@@ -111,18 +111,18 @@ fn is_gcc_lto_obj<E: Layout>(data: &[u8], has_gcc_plugin: bool) -> bool {
|
||||
let syms = records_from_bytes::<ElfSym<E>>(bytes).iter();
|
||||
let skip = |ty: u32| ty == STT_NOTYPE || ty == STT_FILE || ty == STT_SECTION;
|
||||
|
||||
if let Some(sym) = syms.skip(1).find(|s| !skip(s.st_type())) {
|
||||
if sym.st_shndx().get() as u32 == SHN_COMMON {
|
||||
let Some(strtab) = shdrs.get(shdr.sh_link.get() as usize) else {
|
||||
return false;
|
||||
};
|
||||
let name = crate::util::cstr_at(
|
||||
data,
|
||||
strtab.sh_offset.get() as usize + sym.st_name().get() as usize,
|
||||
);
|
||||
if name.starts_with(b"__gnu_lto_") {
|
||||
return true;
|
||||
}
|
||||
if let Some(sym) = syms.skip(1).find(|s| !skip(s.st_type()))
|
||||
&& sym.st_shndx().get() as u32 == SHN_COMMON
|
||||
{
|
||||
let Some(strtab) = shdrs.get(shdr.sh_link.get() as usize) else {
|
||||
return false;
|
||||
};
|
||||
let name = crate::util::cstr_at(
|
||||
data,
|
||||
strtab.sh_offset.get() as usize + sym.st_name().get() as usize,
|
||||
);
|
||||
if name.starts_with(b"__gnu_lto_") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
+20
-20
@@ -189,30 +189,30 @@ fn visit_section<'scope, E: Arch>(
|
||||
// defined. A single such reference can keep an enormous number of
|
||||
// sections alive, so we spread the fanout over threads instead
|
||||
// of marking the sections one by one.
|
||||
if let Some(name) = start_stop_name(sym.name()) {
|
||||
if let Some(sections) = map.get(name) {
|
||||
// Mark targets in parallel. mark_section returns true only for
|
||||
// newly marked sections, which the batch visitor must then visit
|
||||
// unconditionally.
|
||||
sections.par_chunks(GC_BATCH).for_each(|sections| {
|
||||
let mut found = Vec::with_capacity(sections.len());
|
||||
for &target in sections {
|
||||
if mark_section(target) {
|
||||
found.push(target);
|
||||
}
|
||||
if let Some(name) = start_stop_name(sym.name())
|
||||
&& let Some(sections) = map.get(name)
|
||||
{
|
||||
// Mark targets in parallel. mark_section returns true only for
|
||||
// newly marked sections, which the batch visitor must then visit
|
||||
// unconditionally.
|
||||
sections.par_chunks(GC_BATCH).for_each(|sections| {
|
||||
let mut found = Vec::with_capacity(sections.len());
|
||||
for &target in sections {
|
||||
if mark_section(target) {
|
||||
found.push(target);
|
||||
}
|
||||
if !found.is_empty() {
|
||||
visit_batch(ctx, &found, map, scope);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if !found.is_empty() {
|
||||
visit_batch(ctx, &found, map, scope);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if E::FAMILY == Family::Arm32 {
|
||||
if let Some(exidx) = isec.exidx() {
|
||||
mark(file.section_at(exidx));
|
||||
}
|
||||
if E::FAMILY == Family::Arm32
|
||||
&& let Some(exidx) = isec.exidx()
|
||||
{
|
||||
mark(file.section_at(exidx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -1360,11 +1360,11 @@ impl<E: Arch> ObjectFile<E> {
|
||||
|
||||
/// Marks a section dead along with its FDEs.
|
||||
pub fn kill_section(&self, shndx: usize) {
|
||||
if let Some(isec) = self.section(shndx) {
|
||||
if isec.kill() {
|
||||
for fde in isec.fdes(self) {
|
||||
fde.kill();
|
||||
}
|
||||
if let Some(isec) = self.section(shndx)
|
||||
&& isec.kill()
|
||||
{
|
||||
for fde in isec.fdes(self) {
|
||||
fde.kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2005,10 +2005,10 @@ impl<E: Arch> ObjectFile<E> {
|
||||
sym.set_sym_idx(i as u32);
|
||||
sym.set_esym(esym);
|
||||
sym.set_rust(self.is_rust_obj);
|
||||
if let Some(shndx) = shndx {
|
||||
if let Some(section) = self.section_id(shndx) {
|
||||
sym.set_input_section(section);
|
||||
}
|
||||
if let Some(shndx) = shndx
|
||||
&& let Some(section) = self.section_id(shndx)
|
||||
{
|
||||
sym.set_input_section(section);
|
||||
}
|
||||
slots[next].write(sym);
|
||||
self.base.symbols[i] = SymbolId(base_id.0 + next as u32);
|
||||
@@ -2848,10 +2848,10 @@ fn should_write_to_local_symtab<E: Arch>(ctx: &Context<E>, sym: &Symbol) -> bool
|
||||
if ctx.args.discard_locals {
|
||||
return false;
|
||||
}
|
||||
if let Some(isec) = sym.input_section_ref(ctx) {
|
||||
if isec.sh_flags & SHF_MERGE as u64 != 0 {
|
||||
return false;
|
||||
}
|
||||
if let Some(isec) = sym.input_section_ref(ctx)
|
||||
&& isec.sh_flags & SHF_MERGE as u64 != 0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
|
||||
@@ -849,10 +849,11 @@ impl<E: Arch> InputSection<E> {
|
||||
// If the section was dead due to ICF, we don't want to emit debug
|
||||
// info for that section but want to set real values to .debug_line so
|
||||
// that users can set a breakpoint inside a merged section.
|
||||
if let Some(isec) = isec {
|
||||
if isec.is_icf_removed() && name == b".debug_line" {
|
||||
return None;
|
||||
}
|
||||
if let Some(isec) = isec
|
||||
&& isec.is_icf_removed()
|
||||
&& name == b".debug_line"
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// 0 is an invalid value in most debug info sections, so we use it
|
||||
|
||||
+15
-16
@@ -141,17 +141,16 @@ fn resolve_path<E: Arch>(
|
||||
let chroot = &ctx.args.chroot;
|
||||
let open = |path: &Path| -> Option<&'static MappedFile> {
|
||||
let mf = open_file(chroot, path)?;
|
||||
if check_target {
|
||||
if let Some(target) = reader::get_machine_type(ctx, rctx, mf) {
|
||||
if target != E::NAME {
|
||||
warn!(
|
||||
"{}: skipping incompatible file: {target} (e_machine {})",
|
||||
path.display(),
|
||||
E::E_MACHINE
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if check_target
|
||||
&& let Some(target) = reader::get_machine_type(ctx, rctx, mf)
|
||||
&& target != E::NAME
|
||||
{
|
||||
warn!(
|
||||
"{}: skipping incompatible file: {target} (e_machine {})",
|
||||
path.display(),
|
||||
E::E_MACHINE
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Some(mf)
|
||||
};
|
||||
@@ -425,11 +424,11 @@ impl<'a, E: Arch> Script<'a, E> {
|
||||
tok = self.skip(tok, "{");
|
||||
tok = self.read_version_script_commands(tok, ver_str, ver_idx, true, false);
|
||||
tok = self.skip(tok, "}");
|
||||
if let Some(&t) = tok.first() {
|
||||
if t != b";" {
|
||||
// A parent version, e.g. `} VER_1.0;`
|
||||
tok = &tok[1..];
|
||||
}
|
||||
if let Some(&t) = tok.first()
|
||||
&& t != b";"
|
||||
{
|
||||
// A parent version, e.g. `} VER_1.0;`
|
||||
tok = &tok[1..];
|
||||
}
|
||||
tok = self.skip(tok, ";");
|
||||
}
|
||||
|
||||
+5
-4
@@ -22,10 +22,11 @@ fn section_symbols<E: Arch>(ctx: &Context<E>) -> HashMap<InputSectionId, Vec<Sym
|
||||
let file_id = FileId::Obj(file.id());
|
||||
for &id in &file.base.symbols {
|
||||
let sym = &ctx.symbols[id];
|
||||
if sym.file() == Some(file_id) && sym.ty() != STT_SECTION {
|
||||
if let Some(r) = sym.input_section() {
|
||||
map.entry(r).or_default().push(id);
|
||||
}
|
||||
if sym.file() == Some(file_id)
|
||||
&& sym.ty() != STT_SECTION
|
||||
&& let Some(r) = sym.input_section()
|
||||
{
|
||||
map.entry(r).or_default().push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+74
-77
@@ -261,17 +261,13 @@ fn mark_live_file<E: Arch>(ctx: &Context<E>, id: FileId) -> Vec<FileId> {
|
||||
let id2 = file.symbols2[i];
|
||||
let target =
|
||||
if id2 != SymbolId::NONE { ctx.symbols[id2].file() } else { sym.file() };
|
||||
if let Some(target) = target {
|
||||
if (!target.is_dso() || !ctx.args.allow_shlib_undefined)
|
||||
&& ctx.file(target).mark_reachable()
|
||||
{
|
||||
found.push(target);
|
||||
if sym.is_traced() {
|
||||
out!(
|
||||
"trace-symbol: {file} keeps {} for {sym}",
|
||||
ctx.file_display(target)
|
||||
);
|
||||
}
|
||||
if let Some(target) = target
|
||||
&& (!target.is_dso() || !ctx.args.allow_shlib_undefined)
|
||||
&& ctx.file(target).mark_reachable()
|
||||
{
|
||||
found.push(target);
|
||||
if sym.is_traced() {
|
||||
out!("trace-symbol: {file} keeps {} for {sym}", ctx.file_display(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,11 +737,11 @@ pub fn resolve_symbols<E: Arch>(ctx: &mut Context<E>) {
|
||||
|
||||
let mut roots = Vec::new();
|
||||
for &id in &hidden {
|
||||
if let Some(file) = ctx.symbols[id].file() {
|
||||
if !ctx.file(file).is_reachable() {
|
||||
ctx.file(file).set_reachable(true);
|
||||
roots.push(file);
|
||||
}
|
||||
if let Some(file) = ctx.symbols[id].file()
|
||||
&& !ctx.file(file).is_reachable()
|
||||
{
|
||||
ctx.file(file).set_reachable(true);
|
||||
roots.push(file);
|
||||
}
|
||||
}
|
||||
mark_live_files(ctx, roots);
|
||||
@@ -1723,10 +1719,10 @@ pub fn check_duplicate_symbols<E: Arch>(ctx: &Context<E>) {
|
||||
// Skip if one side is an LTO IR object and the other is not.
|
||||
// The LTO backend resolves conflicts between IR and regular objects
|
||||
// on its own; only IR-vs-IR duplicates need to be caught here.
|
||||
if let FileId::Obj(o) = owner {
|
||||
if ctx.objs[o.index()].is_lto_input() != file.is_lto_input() {
|
||||
continue;
|
||||
}
|
||||
if let FileId::Obj(o) = owner
|
||||
&& ctx.objs[o.index()].is_lto_input() != file.is_lto_input()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
error!("duplicate symbol: {file}: {}: {sym}", ctx.file_display(owner));
|
||||
}
|
||||
@@ -1762,15 +1758,16 @@ pub fn check_symbol_version_conflicts<E: Arch>(ctx: &Context<E>) {
|
||||
return;
|
||||
}
|
||||
let sym2 = &ctx.symbols[id2];
|
||||
if let Some(FileId::Obj(_)) = sym2.file() {
|
||||
if !sym2.is_weak() && sym2.ver_idx as u32 == (sym.ver_idx as u32 & !VERSYM_HIDDEN) {
|
||||
let file = &ctx.objs[obj.index()];
|
||||
error!(
|
||||
"duplicate symbol: {file}: {}: {}",
|
||||
ctx.file_display(sym2.file().unwrap()),
|
||||
crate::util::display(file.base.symbol_name_in(sym.sym_idx() as usize))
|
||||
);
|
||||
}
|
||||
if let Some(FileId::Obj(_)) = sym2.file()
|
||||
&& !sym2.is_weak()
|
||||
&& sym2.ver_idx as u32 == (sym.ver_idx as u32 & !VERSYM_HIDDEN)
|
||||
{
|
||||
let file = &ctx.objs[obj.index()];
|
||||
error!(
|
||||
"duplicate symbol: {file}: {}: {}",
|
||||
ctx.file_display(sym2.file().unwrap()),
|
||||
crate::util::display(file.base.symbol_name_in(sym.sym_idx() as usize))
|
||||
);
|
||||
}
|
||||
});
|
||||
crate::error::checkpoint();
|
||||
@@ -1895,19 +1892,18 @@ pub fn check_symbol_types<E: Arch>(ctx: &Context<E>) {
|
||||
};
|
||||
let check = |file: &dyn std::fmt::Display, file_id: FileId, sym: &Symbol, st_type2: u32| {
|
||||
let esym1 = &sym.esym(ctx);
|
||||
if let Some(owner) = sym.file() {
|
||||
if owner != file_id
|
||||
&& esym1.st_type() != STT_NOTYPE
|
||||
&& st_type2 != STT_NOTYPE
|
||||
&& canonicalize(esym1.st_type()) != canonicalize(st_type2)
|
||||
{
|
||||
warn!(
|
||||
"symbol type mismatch: {sym}\n>>> defined in {} as {}\n>>> defined in {file} as {}",
|
||||
ctx.file_display(owner),
|
||||
stt_to_string(esym1.st_type()),
|
||||
stt_to_string(st_type2)
|
||||
);
|
||||
}
|
||||
if let Some(owner) = sym.file()
|
||||
&& owner != file_id
|
||||
&& esym1.st_type() != STT_NOTYPE
|
||||
&& st_type2 != STT_NOTYPE
|
||||
&& canonicalize(esym1.st_type()) != canonicalize(st_type2)
|
||||
{
|
||||
warn!(
|
||||
"symbol type mismatch: {sym}\n>>> defined in {} as {}\n>>> defined in {file} as {}",
|
||||
ctx.file_display(owner),
|
||||
stt_to_string(esym1.st_type()),
|
||||
stt_to_string(st_type2)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2249,10 +2245,10 @@ pub fn compute_section_sizes<E: Arch>(ctx: &mut Context<E>) {
|
||||
// create_range_extension_thunks is not thread-safe
|
||||
for i in 0..ctx.chunks.len() {
|
||||
let id = ctx.chunks[i];
|
||||
if let ChunkId::Output(osec) = id {
|
||||
if needs_thunks(ctx, id) {
|
||||
crate::thunks::create_range_extension_thunks(ctx, osec);
|
||||
}
|
||||
if let ChunkId::Output(osec) = id
|
||||
&& needs_thunks(ctx, id)
|
||||
{
|
||||
crate::thunks::create_range_extension_thunks(ctx, osec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,10 +2345,10 @@ pub fn claim_unresolved_symbols<E: Arch>(ctx: &mut Context<E>) {
|
||||
|
||||
{
|
||||
let sym = &ctx.symbols[id];
|
||||
if let Some(owner) = sym.file() {
|
||||
if !sym.is_undef() || ctx.file(owner).priority <= priority {
|
||||
continue;
|
||||
}
|
||||
if let Some(owner) = sym.file()
|
||||
&& (!sym.is_undef() || ctx.file(owner).priority <= priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2895,16 +2891,17 @@ pub fn parse_symbol_version<E: Arch>(ctx: &mut Context<E>) {
|
||||
// versioned symbol. Likewise, if `foo@VERSION` and `foo@@VERSION` are
|
||||
// defined, the default one takes precedence.
|
||||
let sym_name = ctx.symbols[id].name();
|
||||
if let Some(id2) = ctx.symbols.lookup(sym_name) {
|
||||
if id2 != id && ctx.symbols[id2].file() == Some(file_id) {
|
||||
let sym2_idx = ctx.symbols[id2].sym_idx() as usize;
|
||||
if !file.has_symver[sym2_idx - file.base.first_global] {
|
||||
let v2 = ctx.symbols[id2].ver_idx as u32;
|
||||
if v2 == ctx.default_version as u32
|
||||
|| (v2 & !VERSYM_HIDDEN) == (ver_idx as u32 & !VERSYM_HIDDEN)
|
||||
{
|
||||
ctx.symbols[id2].ver_idx = VER_NDX_LOCAL as u16;
|
||||
}
|
||||
if let Some(id2) = ctx.symbols.lookup(sym_name)
|
||||
&& id2 != id
|
||||
&& ctx.symbols[id2].file() == Some(file_id)
|
||||
{
|
||||
let sym2_idx = ctx.symbols[id2].sym_idx() as usize;
|
||||
if !file.has_symver[sym2_idx - file.base.first_global] {
|
||||
let v2 = ctx.symbols[id2].ver_idx as u32;
|
||||
if v2 == ctx.default_version as u32
|
||||
|| (v2 & !VERSYM_HIDDEN) == (ver_idx as u32 & !VERSYM_HIDDEN)
|
||||
{
|
||||
ctx.symbols[id2].ver_idx = VER_NDX_LOCAL as u16;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3155,10 +3152,10 @@ pub fn compute_address_significance<E: Arch>(ctx: &mut Context<E>) {
|
||||
for r in isec.rels(file) {
|
||||
if !r.is_func_call::<E>() {
|
||||
let sym = &ctx_ref.symbols[file.base.symbols[r.r_sym() as usize]];
|
||||
if let Some(dst) = sym.input_section_ref(ctx_ref) {
|
||||
if dst.sh_flags & SHF_EXECINSTR as u64 != 0 {
|
||||
dst.set_address_taken();
|
||||
}
|
||||
if let Some(dst) = sym.input_section_ref(ctx_ref)
|
||||
&& dst.sh_flags & SHF_EXECINSTR as u64 != 0
|
||||
{
|
||||
dst.set_address_taken();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3820,14 +3817,14 @@ pub fn fix_synthetic_symbols<E: Arch>(ctx: &mut Context<E>) {
|
||||
start(ctx, ctx.syms.bss_start, Some(bss), 0);
|
||||
}
|
||||
|
||||
if let Some(ehdr) = &ctx.ehdr {
|
||||
if ehdr.is_alloc() {
|
||||
let addr = ehdr.shdr.sh_addr.get();
|
||||
for sym in [ctx.syms.ehdr_start, ctx.syms.executable_start] {
|
||||
if let (Some(sym), Some(first)) = (sym, first) {
|
||||
let s = ctx.set_symbol_output_chunk(sym, first);
|
||||
s.value = addr;
|
||||
}
|
||||
if let Some(ehdr) = &ctx.ehdr
|
||||
&& ehdr.is_alloc()
|
||||
{
|
||||
let addr = ehdr.shdr.sh_addr.get();
|
||||
for sym in [ctx.syms.ehdr_start, ctx.syms.executable_start] {
|
||||
if let (Some(sym), Some(first)) = (sym, first) {
|
||||
let s = ctx.set_symbol_output_chunk(sym, first);
|
||||
s.value = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3925,11 +3922,11 @@ pub fn fix_synthetic_symbols<E: Arch>(ctx: &mut Context<E>) {
|
||||
}
|
||||
}
|
||||
// ARM32's __exidx_{start,end}
|
||||
if ctx.syms.exidx_start.is_some() {
|
||||
if let Some(c) = find(ctx, b".ARM.exidx") {
|
||||
start(ctx, ctx.syms.exidx_start, Some(c), 0);
|
||||
stop(ctx, ctx.syms.exidx_end, Some(c), 0);
|
||||
}
|
||||
if ctx.syms.exidx_start.is_some()
|
||||
&& let Some(c) = find(ctx, b".ARM.exidx")
|
||||
{
|
||||
start(ctx, ctx.syms.exidx_start, Some(c), 0);
|
||||
stop(ctx, ctx.syms.exidx_end, Some(c), 0);
|
||||
}
|
||||
// PPC64's ".TOC." symbol.
|
||||
if E::IS_PPC64 {
|
||||
|
||||
+19
-23
@@ -205,26 +205,22 @@ pub fn detect_machine_type<E: Arch>(ctx: &mut Context<E>, jobs: &[ReaderJob]) ->
|
||||
if job.is_lib {
|
||||
continue;
|
||||
}
|
||||
if let Some(mf) = open_file(&ctx.args.chroot, &job.name) {
|
||||
if get_file_type(ctx, mf) != FileType::Text {
|
||||
if let Some(target) =
|
||||
filetype::get_machine_type(&ctx.args.plugin, &ctx.args.chroot, mf)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
if let Some(mf) = open_file(&ctx.args.chroot, &job.name)
|
||||
&& get_file_type(ctx, mf) != FileType::Text
|
||||
&& let Some(target) = filetype::get_machine_type(&ctx.args.plugin, &ctx.args.chroot, mf)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
for job in jobs {
|
||||
if job.is_lib {
|
||||
continue;
|
||||
}
|
||||
if let Some(mf) = open_file(&ctx.args.chroot, &job.name) {
|
||||
if get_file_type(ctx, mf) == FileType::Text {
|
||||
if let Some(target) = crate::linker_script::output_target(ctx, &job.rctx, mf) {
|
||||
return target;
|
||||
}
|
||||
}
|
||||
if let Some(mf) = open_file(&ctx.args.chroot, &job.name)
|
||||
&& get_file_type(ctx, mf) == FileType::Text
|
||||
&& let Some(target) = crate::linker_script::output_target(ctx, &job.rctx, mf)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
fatal!("-m option is missing");
|
||||
@@ -236,15 +232,15 @@ fn open_library<E: Arch>(
|
||||
path: &std::path::Path,
|
||||
) -> Option<&'static MappedFile> {
|
||||
let mf = open_file(&ctx.args.chroot, path)?;
|
||||
if let Some(target) = get_machine_type(ctx, rctx, mf) {
|
||||
if target != E::NAME {
|
||||
warn!(
|
||||
"{}: skipping incompatible file: {target} (e_machine {})",
|
||||
path.display(),
|
||||
E::E_MACHINE
|
||||
);
|
||||
return None;
|
||||
}
|
||||
if let Some(target) = get_machine_type(ctx, rctx, mf)
|
||||
&& target != E::NAME
|
||||
{
|
||||
warn!(
|
||||
"{}: skipping incompatible file: {target} (e_machine {})",
|
||||
path.display(),
|
||||
E::E_MACHINE
|
||||
);
|
||||
return None;
|
||||
}
|
||||
Some(mf)
|
||||
}
|
||||
|
||||
+4
-4
@@ -127,10 +127,10 @@ fn claim_unresolved_symbols<E: Arch>(ctx: &mut Context<E>) {
|
||||
}
|
||||
let id = file.base.symbols[i];
|
||||
let sym = &ctx.symbols[id];
|
||||
if let Some(owner) = sym.file() {
|
||||
if !sym.is_undef() || ctx.file(owner).priority <= priority {
|
||||
continue;
|
||||
}
|
||||
if let Some(owner) = sym.file()
|
||||
&& (!sym.is_undef() || ctx.file(owner).priority <= priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let sym = &mut ctx.symbols[id];
|
||||
sym.set_file(FileId::Obj(file.id()));
|
||||
|
||||
+4
-4
@@ -1219,10 +1219,10 @@ impl Symbol {
|
||||
|
||||
impl fmt::Display for Symbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if demangle_enabled() {
|
||||
if let Some(name) = self.demangled() {
|
||||
return f.write_str(&name);
|
||||
}
|
||||
if demangle_enabled()
|
||||
&& let Some(name) = self.demangled()
|
||||
{
|
||||
return f.write_str(&name);
|
||||
}
|
||||
write!(f, "{}", self.name())
|
||||
}
|
||||
|
||||
+4
-4
@@ -127,10 +127,10 @@ impl Pattern {
|
||||
}
|
||||
|
||||
fn matches(&self, s: &[u8]) -> bool {
|
||||
if let Some(Token::Str(suffix)) = self.tokens.last() {
|
||||
if !s.ends_with(suffix) {
|
||||
return false;
|
||||
}
|
||||
if let Some(Token::Str(suffix)) = self.tokens.last()
|
||||
&& !s.ends_with(suffix)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut x = 0;
|
||||
|
||||
+6
-6
@@ -250,12 +250,12 @@ fn native_machine() -> String {
|
||||
return canonical_machine(&machine.to_string_lossy());
|
||||
}
|
||||
|
||||
if let Ok(output) = Command::new("cc").arg("-dumpmachine").output() {
|
||||
if output.status.success() {
|
||||
let triple = String::from_utf8_lossy(&output.stdout);
|
||||
if !triple.trim().is_empty() {
|
||||
return machine_from_triple(&triple);
|
||||
}
|
||||
if let Ok(output) = Command::new("cc").arg("-dumpmachine").output()
|
||||
&& output.status.success()
|
||||
{
|
||||
let triple = String::from_utf8_lossy(&output.stdout);
|
||||
if !triple.trim().is_empty() {
|
||||
return machine_from_triple(&triple);
|
||||
}
|
||||
}
|
||||
canonical_machine(env::consts::ARCH)
|
||||
|
||||
Reference in new issue
Block a user