diff --git a/src/mold.h b/src/mold.h index 33dc0e5c92..a572d54642 100644 --- a/src/mold.h +++ b/src/mold.h @@ -1028,9 +1028,22 @@ class NotePropertySection : public Chunk { void copy_buf(Context &ctx) override; private: - static constexpr i64 ENTRY_SIZE = E::is_64 ? 16 : 12; + struct Entry64 { + ul32 type; + ul32 size; + ul32 flags; + u32 padding; + }; + + struct Entry32 { + ul32 type; + ul32 size; + ul32 flags; + }; - std::map properties; + using Entry = std::conditional_t; + + std::vector contents; }; template @@ -1809,6 +1822,11 @@ struct SectionOrder { template struct ContextExtras {}; +template +struct ContextExtras { + NotePropertySection *note_property = nullptr; +}; + template <> struct ContextExtras { Arm32ExidxSection *exidx = nullptr; @@ -2080,7 +2098,6 @@ struct Context { VerdefSection *verdef = nullptr; BuildIdSection *buildid = nullptr; NotePackageSection *note_package = nullptr; - NotePropertySection *note_property = nullptr; GdbIndexSection *gdb_index = nullptr; RelroPaddingSection *relro_padding = nullptr; MergedSection *comment = nullptr; diff --git a/src/output-chunks.cc b/src/output-chunks.cc index b3808a1803..cc69cb7dda 100644 --- a/src/output-chunks.cc +++ b/src/output-chunks.cc @@ -2760,12 +2760,7 @@ void NotePackageSection::copy_buf(Context &ctx) { // Merges input files' .note.gnu.property values. template void NotePropertySection::update_shdr(Context &ctx) { - // The rules we support are only specified for x86 psABI - if (!is_x86) - return; - - // Reset to the initial state so that this function is idempotent - properties.clear(); + std::map map; // Obtain the list of keys std::vector *> files = ctx.objs; @@ -2793,41 +2788,41 @@ void NotePropertySection::update_shdr(Context &ctx) { key <= GNU_PROPERTY_X86_UINT32_AND_HI) { // An AND feature is set if all input objects have the property and // the feature. - if (std::all_of(files.begin(), files.end(), has_key)) { - properties[key] = 0xffff'ffff; - for (ObjectFile *file : files) - properties[key] &= get_value(file, key); - } + map[key] = 0xffff'ffff; + for (ObjectFile *file : files) + map[key] &= get_value(file, key); } else if (GNU_PROPERTY_X86_UINT32_OR_LO <= key && key <= GNU_PROPERTY_X86_UINT32_OR_HI) { // An OR feature is set if some input object has the feature. for (ObjectFile *file : files) - properties[key] |= get_value(file, key); + map[key] |= get_value(file, key); } else if (GNU_PROPERTY_X86_UINT32_OR_AND_LO <= key && key <= GNU_PROPERTY_X86_UINT32_OR_AND_HI) { // An OR-AND feature is set if all input object files have the property // and some of them has the feature. if (std::all_of(files.begin(), files.end(), has_key)) for (ObjectFile *file : files) - properties[key] |= get_value(file, key); + map[key] |= get_value(file, key); } } if (ctx.arg.z_ibt) - properties[GNU_PROPERTY_X86_FEATURE_1_AND] |= GNU_PROPERTY_X86_FEATURE_1_IBT; + map[GNU_PROPERTY_X86_FEATURE_1_AND] |= GNU_PROPERTY_X86_FEATURE_1_IBT; if (ctx.arg.z_shstk) - properties[GNU_PROPERTY_X86_FEATURE_1_AND] |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; + map[GNU_PROPERTY_X86_FEATURE_1_AND] |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; + map[GNU_PROPERTY_X86_ISA_1_NEEDED] |= ctx.arg.z_x86_64_isa_level; - properties[GNU_PROPERTY_X86_ISA_1_NEEDED] |= ctx.arg.z_x86_64_isa_level; + // Serialize the map + contents.clear(); - std::erase_if(properties, [](std::pair kv) { - return kv.second == 0; - }); + for (std::pair kv : map) + if (kv.second) + contents.push_back({kv.first, 4, kv.second}); - if (properties.empty()) + if (contents.empty()) this->shdr.sh_size = 0; else - this->shdr.sh_size = 16 + ENTRY_SIZE * properties.size(); + this->shdr.sh_size = 16 + contents.size() * sizeof(contents[0]); } template @@ -2835,18 +2830,11 @@ void NotePropertySection::copy_buf(Context &ctx) { U32 *buf = (U32 *)(ctx.buf + this->shdr.sh_offset); memset(buf, 0, this->shdr.sh_size); - buf[0] = 4; // Name size - buf[1] = ENTRY_SIZE * properties.size(); // Content size - buf[2] = NT_GNU_PROPERTY_TYPE_0; // Type - memcpy(buf + 3, "GNU", 4); // Name - - i64 idx = 4; - for (std::pair kv : properties) { - buf[idx] = kv.first; // Feature type - buf[idx + 1] = 4; // Feature size - buf[idx + 2] = kv.second; // Feature flags - idx += ENTRY_SIZE / sizeof(U32); - } + buf[0] = 4; // Name size + buf[1] = this->shdr.sh_size - 16; // Content size + buf[2] = NT_GNU_PROPERTY_TYPE_0; // Type + memcpy(buf + 3, "GNU", 4); // Name + write_vector(buf + 4, contents); // Content } template diff --git a/src/passes.cc b/src/passes.cc index 103b9010b5..6584bdcc46 100644 --- a/src/passes.cc +++ b/src/passes.cc @@ -176,7 +176,6 @@ void create_synthetic_sections(Context &ctx) { ctx.versym = push(new VersymSection); ctx.verneed = push(new VerneedSection); ctx.note_package = push(new NotePackageSection); - ctx.note_property = push(new NotePropertySection); if (!ctx.arg.oformat_binary) { ElfShdr shdr = {}; @@ -185,6 +184,9 @@ void create_synthetic_sections(Context &ctx) { ctx.comment = MergedSection::get_instance(ctx, ".comment", shdr); } + if constexpr (is_x86) + ctx.extra.note_property = push(new NotePropertySection); + if constexpr (is_riscv) ctx.extra.riscv_attributes = push(new RiscvAttributesSection); diff --git a/src/relocatable.cc b/src/relocatable.cc index 639dc6ae87..1f4e3b941d 100644 --- a/src/relocatable.cc +++ b/src/relocatable.cc @@ -53,7 +53,9 @@ static void r_create_synthetic_sections(Context &ctx) { ctx.strtab = push(new StrtabSection); ctx.symtab = push(new SymtabSection); ctx.shstrtab = push(new ShstrtabSection); - ctx.note_property = push(new NotePropertySection); + + if constexpr (is_x86) + ctx.extra.note_property = push(new NotePropertySection); if constexpr (is_riscv) ctx.extra.riscv_attributes = push(new RiscvAttributesSection);