* commit 'd978d21d195976fa3f257b8d17ec2fe18fb436a7': Honor p_vaddr if set
This commit is contained in:
commit
b181747aa1
@ -226,24 +226,32 @@ bool ElfReader::ReadProgramHeader() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Compute the extent of all loadable segments in an ELF program header
|
||||
* table. This corresponds to the page-aligned size in bytes that needs to be
|
||||
* reserved in the process' address space
|
||||
/* Returns the size of the extent of all the possibly non-contiguous
|
||||
* loadable segments in an ELF program header table. This corresponds
|
||||
* to the page-aligned size in bytes that needs to be reserved in the
|
||||
* process' address space. If there are no loadable segments, 0 is
|
||||
* returned.
|
||||
*
|
||||
* This returns 0 if there are no loadable segments.
|
||||
* If out_min_vaddr or out_max_vaddr are non-NULL, they will be
|
||||
* set to the minimum and maximum addresses of pages to be reserved,
|
||||
* or 0 if there is nothing to load.
|
||||
*/
|
||||
Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
|
||||
size_t phdr_count)
|
||||
size_t phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
|
||||
size_t phdr_count,
|
||||
Elf32_Addr* out_min_vaddr,
|
||||
Elf32_Addr* out_max_vaddr)
|
||||
{
|
||||
Elf32_Addr min_vaddr = 0xFFFFFFFFU;
|
||||
Elf32_Addr max_vaddr = 0x00000000U;
|
||||
|
||||
bool found_pt_load = false;
|
||||
for (size_t i = 0; i < phdr_count; ++i) {
|
||||
const Elf32_Phdr* phdr = &phdr_table[i];
|
||||
|
||||
if (phdr->p_type != PT_LOAD) {
|
||||
continue;
|
||||
}
|
||||
found_pt_load = true;
|
||||
|
||||
if (phdr->p_vaddr < min_vaddr) {
|
||||
min_vaddr = phdr->p_vaddr;
|
||||
@ -253,14 +261,19 @@ Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
|
||||
max_vaddr = phdr->p_vaddr + phdr->p_memsz;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_vaddr > max_vaddr) {
|
||||
return 0;
|
||||
if (!found_pt_load) {
|
||||
min_vaddr = 0x00000000U;
|
||||
}
|
||||
|
||||
min_vaddr = PAGE_START(min_vaddr);
|
||||
max_vaddr = PAGE_END(max_vaddr);
|
||||
|
||||
if (out_min_vaddr != NULL) {
|
||||
*out_min_vaddr = min_vaddr;
|
||||
}
|
||||
if (out_max_vaddr != NULL) {
|
||||
*out_max_vaddr = max_vaddr;
|
||||
}
|
||||
return max_vaddr - min_vaddr;
|
||||
}
|
||||
|
||||
@ -268,29 +281,23 @@ Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
|
||||
// segments of a program header table. This is done by creating a
|
||||
// private anonymous mmap() with PROT_NONE.
|
||||
bool ElfReader::ReserveAddressSpace() {
|
||||
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_);
|
||||
Elf32_Addr min_vaddr;
|
||||
load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
|
||||
if (load_size_ == 0) {
|
||||
DL_ERR("\"%s\" has no loadable segments", name_);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
|
||||
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||
void* start = mmap(NULL, load_size_, PROT_NONE, mmap_flags, -1, 0);
|
||||
void* start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
|
||||
if (start == MAP_FAILED) {
|
||||
DL_ERR("couldn't reserve %d bytes of address space for \"%s\"", load_size_, name_);
|
||||
return false;
|
||||
}
|
||||
|
||||
load_start_ = start;
|
||||
load_bias_ = 0;
|
||||
|
||||
for (size_t i = 0; i < phdr_num_; ++i) {
|
||||
const Elf32_Phdr* phdr = &phdr_table_[i];
|
||||
if (phdr->p_type == PT_LOAD) {
|
||||
load_bias_ = reinterpret_cast<Elf32_Addr>(start) - PAGE_START(phdr->p_vaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,11 @@ class ElfReader {
|
||||
const Elf32_Phdr* loaded_phdr_;
|
||||
};
|
||||
|
||||
Elf32_Addr phdr_table_get_load_size(const Elf32_Phdr* phdr, size_t phnum);
|
||||
size_t
|
||||
phdr_table_get_load_size(const Elf32_Phdr* phdr_table,
|
||||
size_t phdr_count,
|
||||
Elf32_Addr* min_vaddr = NULL,
|
||||
Elf32_Addr* max_vaddr = NULL);
|
||||
|
||||
int
|
||||
phdr_table_protect_segments(const Elf32_Phdr* phdr_table,
|
||||
|
Loading…
Reference in New Issue
Block a user