diff --git a/macho/arch-arm64.cc b/macho/arch-arm64.cc index 724e5bbbb5..4af7187435 100644 --- a/macho/arch-arm64.cc +++ b/macho/arch-arm64.cc @@ -118,12 +118,11 @@ read_relocations(Context &ctx, ObjectFile &file, Relocation &rel = vec.back(); - if (rels[i].type == ARM64_RELOC_SUBTRACTOR || - (i > 0 && rels[i - 1].type == ARM64_RELOC_SUBTRACTOR)) { - rel.is_pcrel = false; - } else { + if (i > 0 && rels[i - 1].type == ARM64_RELOC_SUBTRACTOR) + rel.is_subtracted = true; + + if (!rel.is_subtracted && rels[i].type != ARM64_RELOC_SUBTRACTOR) rel.is_pcrel = r.is_pcrel; - } if (r.is_extern) { rel.sym = file.syms[r.idx]; diff --git a/macho/arch-x86-64.cc b/macho/arch-x86-64.cc index 4f638752b9..2f404598ee 100644 --- a/macho/arch-x86-64.cc +++ b/macho/arch-x86-64.cc @@ -95,12 +95,11 @@ read_relocations(Context &ctx, ObjectFile &file, vec.push_back({r.offset, (u8)r.type, (u8)r.p2size}); Relocation &rel = vec.back(); - if (rels[i].type == X86_64_RELOC_SUBTRACTOR || - (i > 0 && rels[i - 1].type == X86_64_RELOC_SUBTRACTOR)) { - rel.is_pcrel = false; - } else { + if (i > 0 && rels[i - 1].type == X86_64_RELOC_SUBTRACTOR) + rel.is_subtracted = true; + + if (!rel.is_subtracted && rels[i].type != X86_64_RELOC_SUBTRACTOR) rel.is_pcrel = r.is_pcrel; - } if (r.is_extern) { rel.sym = file.syms[r.idx]; diff --git a/macho/mold.h b/macho/mold.h index 2082d9eb19..5215a9a1b7 100644 --- a/macho/mold.h +++ b/macho/mold.h @@ -48,6 +48,7 @@ struct Relocation { u8 type = -1; u8 p2size = 0; bool is_pcrel : 1 = false; + bool is_subtracted : 1 = false; bool needs_dynrel : 1 = false; i64 addend = 0; Symbol *sym = nullptr; diff --git a/macho/output-chunks.cc b/macho/output-chunks.cc index 3d49bda939..320199e67c 100644 --- a/macho/output-chunks.cc +++ b/macho/output-chunks.cc @@ -666,7 +666,8 @@ void RebaseSection::compute_size(Context &ctx) { if (chunk->is_output_section && !chunk->hdr.match("__TEXT", "__eh_frame")) for (Subsection *subsec : ((OutputSection *)chunk)->members) for (Relocation &rel : subsec->get_rels()) - if (!rel.is_pcrel && rel.type == E::abs_rel && !refers_tls(rel.sym)) + if (!rel.is_pcrel && !rel.is_subtracted && rel.type == E::abs_rel && + !refers_tls(rel.sym)) enc.add(seg->seg_idx, subsec->get_addr(ctx) + rel.offset - seg->cmd.vmaddr);