auto [it, inserted] = map.insert({key, osec.get()}); isec->output_section = it->second; if (inserted) ctx.osec_pool.emplace_back(std::move(osec)); } });
1 2 3 4 5
// Add input sections to output sections for (ObjectFile<E> *file : ctx.objs) for (std::unique_ptr<InputSection<E>> &isec : file->sections) if (isec && isec->is_alive) isec->output_section->members.push_back(isec.get());
1 2 3 4 5 6 7 8
// Add output sections and mergeable sections to ctx.chunks std::vector<Chunk<E> *> vec; for (std::pair<const OutputSectionKey, OutputSection<E> *> &kv : map) vec.push_back(kv.second);
for (std::unique_ptr<MergedSection<E>> &osec : ctx.merged_sections) if (osec->shdr.sh_size) vec.push_back(osec.get());
1 2 3 4 5 6 7
// Sections are added to the section lists in an arbitrary order // because they are created in parallel. Sort them to to make the // output deterministic. tbb::parallel_sort(vec.begin(), vec.end(), [](Chunk<E> *x, Chunk<E> *y) { return std::tuple(x->name, x->shdr.sh_type, x->shdr.sh_flags) < std::tuple(y->name, y->shdr.sh_type, y->shdr.sh_flags); });
if (!ctx.arg.relocatable) flags &= ~(u64)SHF_GROUP & ~(u64)SHF_GNU_RETAIN;
// .init_array is usually writable. We don't want to create multiple // .init_array output sections, so make it always writable. // So is .fini_array. if (type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY) flags |= SHF_WRITE; return {name, type, flags}; }
// Make all synthetic symbols relative ones by associating them to // a dummy output section. for (Symbol<E> *sym : obj.symbols) if (sym->file == &obj) sym->set_output_section(ctx.symtab);
Control-flow Enforcement Technology (CET) covers several related x86 processor features that provide protection against control flow hijacking attacks. CET can protect both applications and the kernel.
CET introduces shadow stack and indirect branch tracking (IBT). A shadow stack is a secondary stack allocated from memory which cannot be directly modified by applications. When executing a CALL instruction, the processor pushes the return address to both the normal stack and the shadow stack. Upon function return, the processor pops the shadow stack copy and compares it to the normal stack copy. If the two differ, the processor raises a control-protection fault. IBT verifies indirect CALL/JMP targets are intended as marked by the compiler with ‘ENDBR’ opcodes. Not all CPU’s have both Shadow Stack and Indirect Branch Tracking. Today in the 64-bit kernel, only userspace shadow stack and kernel IBT are supported.
// .note.GNU-stack section controls executable-ness of the stack // area in GNU linkers. We ignore that section because silently // making the stack area executable is too dangerous. Tell our // users about the difference if that matters. if (name == ".note.GNU-stack" && !ctx.arg.relocatable) { if (shdr.sh_flags & SHF_EXECINSTR) { if (!ctx.arg.z_execstack && !ctx.arg.z_execstack_if_needed) Warn(ctx) << *this << ": this file may cause a segmentation" " fault because it requires an executable stack. See" " https://github.com/rui314/mold/tree/main/docs/execstack.md" " for more info."; needs_executable_stack = true; } continue; }