diff options
Diffstat (limited to 'linker/linker_main.cpp')
-rw-r--r-- | linker/linker_main.cpp | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 5dc215f9d..db3697618 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -87,6 +87,7 @@ bool solist_remove_soinfo(soinfo* si) { // prev will never be null, because the first entry in solist is // always the static libdl_info. + CHECK(prev != nullptr); prev->next = si->next; if (si == sonext) { sonext = prev; @@ -307,6 +308,11 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args) { break; } } + + if (si->base == 0) { + async_safe_fatal("Could not find a PHDR: broken executable?"); + } + si->dynamic = nullptr; ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base); @@ -488,6 +494,15 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) { static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr); ElfW(Addr) linker_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr; +#if defined(__clang_analyzer__) + // The analyzer assumes that linker_addr will always be null. Make it an + // unknown value so we don't have to mark N places with NOLINTs. + // + // (`+=`, rather than `=`, allows us to sidestep a potential "unused store" + // complaint) + linker_addr += reinterpret_cast<uintptr_t>(raw_args); +#endif + ElfW(Addr) entry_point = args.getauxval(AT_ENTRY); ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr); ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff); |