| Index: third_party/android_crazy_linker/src/src/crazy_linker_elf_view.cpp
|
| diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..65ec2818533860d0ab2d8f605ef070f99ba96722
|
| --- /dev/null
|
| +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.cpp
|
| @@ -0,0 +1,121 @@
|
| +#include "crazy_linker_elf_view.h"
|
| +
|
| +#include <errno.h>
|
| +
|
| +#include "crazy_linker_debug.h"
|
| +#include "crazy_linker_error.h"
|
| +#include "linker_phdr.h"
|
| +
|
| +namespace crazy {
|
| +
|
| +bool ElfView::InitUnmapped(size_t load_address,
|
| + const ELF::Phdr* phdr,
|
| + size_t phdr_count,
|
| + Error* error) {
|
| + // Compute load size and bias.
|
| + size_t min_vaddr = 0;
|
| + load_size_ = phdr_table_get_load_size(phdr, phdr_count, &min_vaddr, NULL);
|
| + if (load_size_ == 0) {
|
| + *error = "Invalid program header table";
|
| + return false;
|
| + }
|
| + load_address_ = (load_address ? load_address : min_vaddr);
|
| + load_bias_ = load_address - min_vaddr;
|
| +
|
| + // Extract the dynamic table information.
|
| + phdr_table_get_dynamic_section(phdr,
|
| + phdr_count,
|
| + load_address,
|
| + &dynamic_,
|
| + &dynamic_count_,
|
| + &dynamic_flags_);
|
| + if (!dynamic_) {
|
| + *error = "No PT_DYNAMIC section!";
|
| + return false;
|
| + }
|
| +
|
| + // Compute the program header table address relative to load_address.
|
| + // This is different from |phdr|..|phdr + phdr_count| which can actually
|
| + // be at a different location.
|
| + const ELF::Phdr* phdr0 = NULL;
|
| +
|
| + // First, if there is a PT_PHDR, use it directly.
|
| + for (size_t n = 0; n < phdr_count; ++n) {
|
| + const ELF::Phdr* entry = &phdr[n];
|
| + if (entry->p_type == PT_PHDR) {
|
| + phdr0 = entry;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Otherwise, check the first loadable segment. If its file offset
|
| + // is 0, it starts with the ELF header, and we can trivially find the
|
| + // loaded program header from it.
|
| + if (!phdr0) {
|
| + for (size_t n = 0; n < phdr_count; ++n) {
|
| + const ELF::Phdr* entry = &phdr[n];
|
| + if (entry->p_type == PT_LOAD) {
|
| + if (entry->p_offset == 0) {
|
| + ELF::Addr elf_addr = load_bias_ + entry->p_vaddr;
|
| + const ELF::Ehdr* ehdr = reinterpret_cast<const ELF::Ehdr*>(elf_addr);
|
| + ELF::Addr offset = ehdr->e_phoff;
|
| + phdr0 = reinterpret_cast<const ELF::Phdr*>(elf_addr + offset);
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Check that the program header table is indeed in a loadable segment,
|
| + // this helps catching malformed ELF binaries.
|
| + if (phdr0) {
|
| + ELF::Addr phdr0_addr = reinterpret_cast<ELF::Addr>(phdr0);
|
| + ELF::Addr phdr0_limit = phdr0_addr + sizeof(ELF::Phdr) * phdr_count;
|
| + bool found = false;
|
| + for (size_t n = 0; n < phdr_count; ++n) {
|
| + size_t seg_start = load_bias_ + phdr[n].p_vaddr;
|
| + size_t seg_end = seg_start + phdr[n].p_filesz;
|
| +
|
| + if (seg_start <= phdr0_addr && phdr0_limit <= seg_end) {
|
| + found = true;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (!found)
|
| + phdr0 = NULL;
|
| + }
|
| +
|
| + if (!phdr0) {
|
| + *error = "Malformed ELF binary";
|
| + return false;
|
| + }
|
| +
|
| + phdr_ = phdr0;
|
| + phdr_count_ = phdr_count;
|
| +
|
| + LOG("%s: New ELF view [load_address:%p, load_size:%p, load_bias:%p, phdr:%p, "
|
| + "phdr_count:%d, dynamic:%p, dynamic_count:%d, dynamic_flags:%d",
|
| + __FUNCTION__,
|
| + load_address_,
|
| + load_size_,
|
| + load_bias_,
|
| + phdr_,
|
| + phdr_count_,
|
| + dynamic_,
|
| + dynamic_count_,
|
| + dynamic_flags_);
|
| + return true;
|
| +}
|
| +
|
| +bool ElfView::ProtectRelroSection(Error* error) {
|
| + LOG("%s: Enabling GNU RELRO protection\n", __FUNCTION__);
|
| +
|
| + if (phdr_table_protect_gnu_relro(phdr_, phdr_count_, load_bias_) < 0) {
|
| + error->Format("Can't enable GNU RELRO protection: %s", strerror(errno));
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +} // namespace crazy
|
|
|