From 66169958046c66a794483e6eb163a82447236fa6 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Tue, 21 Nov 2023 12:11:13 +0900 Subject: [PATCH] Refactor --- elf/output-chunks.cc | 112 ++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/elf/output-chunks.cc b/elf/output-chunks.cc index 033e3dd5dc..a6f8acbdb9 100644 --- a/elf/output-chunks.cc +++ b/elf/output-chunks.cc @@ -176,8 +176,7 @@ static std::vector> create_phdr(Context &ctx) { }; auto is_bss = [](Chunk *chunk) { - return chunk->shdr.sh_type == SHT_NOBITS && - !(chunk->shdr.sh_flags & SHF_TLS); + return chunk->shdr.sh_type == SHT_NOBITS; }; auto is_tbss = [](Chunk *chunk) { @@ -186,10 +185,16 @@ static std::vector> create_phdr(Context &ctx) { }; auto is_note = [](Chunk *chunk) { - ElfShdr &shdr = chunk->shdr; - return (shdr.sh_type == SHT_NOTE) && (shdr.sh_flags & SHF_ALLOC); + return chunk->shdr.sh_type == SHT_NOTE; }; + // When we are creating PT_LOAD segments, we consider only + // the following chunks. + std::vector *> chunks; + for (Chunk *chunk : ctx.chunks) + if ((chunk->shdr.sh_flags & SHF_ALLOC) && !is_tbss(chunk)) + chunks.push_back(chunk); + // Create a PT_PHDR for the program header itself. if (ctx.phdr && (ctx.phdr->shdr.sh_flags & SHF_ALLOC)) define(PT_PHDR, PF_R, sizeof(Word), ctx.phdr); @@ -199,62 +204,58 @@ static std::vector> create_phdr(Context &ctx) { define(PT_INTERP, PF_R, 1, ctx.interp); // Create a PT_NOTE for SHF_NOTE sections. - for (i64 i = 0, end = ctx.chunks.size(); i < end;) { - Chunk *first = ctx.chunks[i++]; - if (!is_note(first)) - continue; - - i64 flags = to_phdr_flags(ctx, first); - i64 alignment = first->shdr.sh_addralign; - define(PT_NOTE, flags, alignment, first); + for (i64 i = 0; i < chunks.size();) { + Chunk *first = chunks[i++]; + if (is_note(first)) { + i64 flags = to_phdr_flags(ctx, first); + define(PT_NOTE, flags, first->shdr.sh_addralign, first); - while (i < end && is_note(ctx.chunks[i]) && - to_phdr_flags(ctx, ctx.chunks[i]) == flags) - append(ctx.chunks[i++]); + while (i < chunks.size() && + is_note(ctx.chunks[i]) && + to_phdr_flags(ctx, ctx.chunks[i]) == flags) + append(ctx.chunks[i++]); + } } // Create PT_LOAD segments. - { - i64 idx = vec.size(); - std::vector *> chunks = ctx.chunks; - std::erase_if(chunks, is_tbss); + i64 pt_load_begin = vec.size(); - for (i64 i = 0, end = chunks.size(); i < end;) { - Chunk *first = chunks[i++]; - if (!(first->shdr.sh_flags & SHF_ALLOC)) - continue; - - i64 flags = to_phdr_flags(ctx, first); - define(PT_LOAD, flags, ctx.page_size, first); - - // Add contiguous ALLOC sections as long as they have the same - // section flags and there's no on-disk gap in between. - if (!is_bss(first)) - while (i < end && !is_bss(chunks[i]) && - to_phdr_flags(ctx, chunks[i]) == flags && - chunks[i]->shdr.sh_offset - first->shdr.sh_offset == - chunks[i]->shdr.sh_addr - first->shdr.sh_addr) - append(chunks[i++]); - - while (i < end && is_bss(chunks[i]) && - to_phdr_flags(ctx, chunks[i]) == flags) + for (i64 i = 0; i < chunks.size();) { + Chunk *first = chunks[i++]; + i64 flags = to_phdr_flags(ctx, first); + define(PT_LOAD, flags, ctx.page_size, first); + + // Add contiguous ALLOC sections as long as they have the same + // section flags and there's no on-disk gap in between. + if (!is_bss(first)) + while (i < chunks.size() && + !is_bss(chunks[i]) && + to_phdr_flags(ctx, chunks[i]) == flags && + chunks[i]->shdr.sh_offset - first->shdr.sh_offset == + chunks[i]->shdr.sh_addr - first->shdr.sh_addr) append(chunks[i++]); - } - // The ELF spec says that "loadable segment entries in the program - // header table appear in ascending order, sorted on the p_vaddr - // member". - std::stable_sort(vec.begin() + idx, vec.end(), - [](const ElfPhdr &a, const ElfPhdr &b) { - return a.p_vaddr < b.p_vaddr; - }); + while (i < chunks.size() && + is_bss(chunks[i]) && + to_phdr_flags(ctx, chunks[i]) == flags) + append(chunks[i++]); } + // The ELF spec says that "loadable segment entries in the program + // header table appear in ascending order, sorted on the p_vaddr + // member". + std::stable_sort(vec.begin() + pt_load_begin, vec.end(), + [](const ElfPhdr &a, const ElfPhdr &b) { + return a.p_vaddr < b.p_vaddr; + }); + // Create a PT_TLS. - for (i64 i = 0; i < ctx.chunks.size(); i++) { - if (ctx.chunks[i]->shdr.sh_flags & SHF_TLS) { - define(PT_TLS, PF_R, 1, ctx.chunks[i++]); - while (i < ctx.chunks.size() && (ctx.chunks[i]->shdr.sh_flags & SHF_TLS)) + for (i64 i = 0; i < ctx.chunks.size();) { + Chunk *first = ctx.chunks[i++]; + if (first->shdr.sh_flags & SHF_TLS) { + define(PT_TLS, PF_R, 1, first); + while (i < ctx.chunks.size() && + (ctx.chunks[i]->shdr.sh_flags & SHF_TLS)) append(ctx.chunks[i++]); } } @@ -280,11 +281,12 @@ static std::vector> create_phdr(Context &ctx) { // Create a PT_GNU_RELRO. if (ctx.arg.z_relro) { - for (i64 i = 0; i < ctx.chunks.size(); i++) { - if (ctx.chunks[i]->is_relro && !is_tbss(ctx.chunks[i])) { - define(PT_GNU_RELRO, PF_R, 1, ctx.chunks[i++]); - while (i < ctx.chunks.size() && ctx.chunks[i]->is_relro) - append(ctx.chunks[i++]); + for (i64 i = 0; i < chunks.size();) { + Chunk *first = chunks[i++]; + if (first->is_relro) { + define(PT_GNU_RELRO, PF_R, 1, first); + while (i < chunks.size() && chunks[i]->is_relro) + append(chunks[i++]); vec.back().p_align = 1; } }