Merge "refactoring: introduce MappedFileFragment"
am: e08ab4b414 * commit 'e08ab4b4144b8c4c920221b403daa220b43df2fb': refactoring: introduce MappedFileFragment
This commit is contained in:
commit
67e282d511
@ -12,6 +12,7 @@ LOCAL_SRC_FILES := \
|
|||||||
linker_sdk_versions.cpp \
|
linker_sdk_versions.cpp \
|
||||||
linker_block_allocator.cpp \
|
linker_block_allocator.cpp \
|
||||||
linker_libc_support.c \
|
linker_libc_support.c \
|
||||||
|
linker_mapped_file_fragment.cpp \
|
||||||
linker_memory.cpp \
|
linker_memory.cpp \
|
||||||
linker_phdr.cpp \
|
linker_phdr.cpp \
|
||||||
linker_utils.cpp \
|
linker_utils.cpp \
|
||||||
|
@ -58,6 +58,13 @@
|
|||||||
|
|
||||||
__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
|
__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
|
||||||
|
|
||||||
|
#define CHECK(predicate) { \
|
||||||
|
if (!(predicate)) { \
|
||||||
|
__libc_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
|
||||||
|
__FILE__, __LINE__, __FUNCTION__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#if LINKER_DEBUG_TO_LOG
|
#if LINKER_DEBUG_TO_LOG
|
||||||
#define _PRINTVF(v, x...) \
|
#define _PRINTVF(v, x...) \
|
||||||
do { \
|
do { \
|
||||||
|
82
linker/linker_mapped_file_fragment.cpp
Normal file
82
linker/linker_mapped_file_fragment.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "linker_mapped_file_fragment.h"
|
||||||
|
#include "linker_debug.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1);
|
||||||
|
|
||||||
|
static off64_t page_start(off64_t offset) {
|
||||||
|
return offset & kPageMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool safe_add(off64_t* out, off64_t a, size_t b) {
|
||||||
|
CHECK(a >= 0);
|
||||||
|
if (static_cast<uint64_t>(INT64_MAX - a) < b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = a + b;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t page_offset(off64_t offset) {
|
||||||
|
return static_cast<size_t>(offset & (PAGE_SIZE-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
MappedFileFragment::MappedFileFragment() : map_start_(nullptr), map_size_(0),
|
||||||
|
data_(nullptr), size_ (0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
MappedFileFragment::~MappedFileFragment() {
|
||||||
|
if (map_start_ != nullptr) {
|
||||||
|
munmap(map_start_, map_size_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MappedFileFragment::Map(int fd, off64_t base_offset, size_t elf_offset, size_t size) {
|
||||||
|
off64_t offset;
|
||||||
|
CHECK(safe_add(&offset, base_offset, elf_offset));
|
||||||
|
|
||||||
|
off64_t page_min = page_start(offset);
|
||||||
|
off64_t end_offset;
|
||||||
|
|
||||||
|
CHECK(safe_add(&end_offset, offset, size));
|
||||||
|
CHECK(safe_add(&end_offset, end_offset, page_offset(offset)));
|
||||||
|
|
||||||
|
size_t map_size = static_cast<size_t>(end_offset - page_min);
|
||||||
|
CHECK(map_size >= size);
|
||||||
|
|
||||||
|
uint8_t* map_start = static_cast<uint8_t*>(
|
||||||
|
mmap64(nullptr, map_size, PROT_READ, MAP_PRIVATE, fd, page_min));
|
||||||
|
|
||||||
|
if (map_start == MAP_FAILED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
map_start_ = map_start;
|
||||||
|
map_size_ = map_size;
|
||||||
|
|
||||||
|
data_ = map_start + page_offset(offset);
|
||||||
|
size_ = size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
41
linker/linker_mapped_file_fragment.h
Normal file
41
linker/linker_mapped_file_fragment.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef LINKER_MAPPED_FILE_FRAGMENT_H
|
||||||
|
#define LINKER_MAPPED_FILE_FRAGMENT_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "private/bionic_macros.h"
|
||||||
|
|
||||||
|
class MappedFileFragment {
|
||||||
|
public:
|
||||||
|
MappedFileFragment();
|
||||||
|
~MappedFileFragment();
|
||||||
|
|
||||||
|
bool Map(int fd, off64_t base_offset, size_t elf_offset, size_t size);
|
||||||
|
|
||||||
|
void* data() const { return data_; }
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
private:
|
||||||
|
void* map_start_;
|
||||||
|
size_t map_size_;
|
||||||
|
void* data_;
|
||||||
|
size_t size_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MappedFileFragment);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LINKER_MAPPED_FILE_FRAGMENT_H */
|
@ -134,18 +134,11 @@ static int GetTargetElfMachine() {
|
|||||||
MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
|
MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
|
||||||
|
|
||||||
ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
|
ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
|
||||||
: name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size),
|
: name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size), phdr_num_(0),
|
||||||
phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
|
phdr_table_(nullptr), load_start_(nullptr), load_size_(0), load_bias_(0),
|
||||||
load_start_(nullptr), load_size_(0), load_bias_(0),
|
|
||||||
loaded_phdr_(nullptr) {
|
loaded_phdr_(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfReader::~ElfReader() {
|
|
||||||
if (phdr_mmap_ != nullptr) {
|
|
||||||
munmap(phdr_mmap_, phdr_size_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ElfReader::Load(const android_dlextinfo* extinfo) {
|
bool ElfReader::Load(const android_dlextinfo* extinfo) {
|
||||||
return ReadElfHeader() &&
|
return ReadElfHeader() &&
|
||||||
VerifyElfHeader() &&
|
VerifyElfHeader() &&
|
||||||
@ -234,21 +227,12 @@ bool ElfReader::ReadProgramHeader() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElfW(Addr) page_min = PAGE_START(header_.e_phoff);
|
if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, phdr_num_ * sizeof(ElfW(Phdr)))) {
|
||||||
ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
|
|
||||||
ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
|
|
||||||
|
|
||||||
phdr_size_ = page_max - page_min;
|
|
||||||
|
|
||||||
void* mmap_result =
|
|
||||||
mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
|
|
||||||
if (mmap_result == MAP_FAILED) {
|
|
||||||
DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
|
DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
phdr_mmap_ = mmap_result;
|
phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
|
||||||
phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,7 +813,7 @@ bool ElfReader::FindPhdr() {
|
|||||||
bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
|
bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
|
||||||
const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
|
const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
|
||||||
ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
|
ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
|
||||||
for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
|
for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
|
||||||
if (phdr->p_type != PT_LOAD) {
|
if (phdr->p_type != PT_LOAD) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linker.h"
|
#include "linker.h"
|
||||||
|
#include "linker_mapped_file_fragment.h"
|
||||||
|
|
||||||
class ElfReader {
|
class ElfReader {
|
||||||
public:
|
public:
|
||||||
ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size);
|
ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size);
|
||||||
~ElfReader();
|
|
||||||
|
|
||||||
bool Load(const android_dlextinfo* extinfo);
|
bool Load(const android_dlextinfo* extinfo);
|
||||||
|
|
||||||
@ -67,9 +67,8 @@ class ElfReader {
|
|||||||
ElfW(Ehdr) header_;
|
ElfW(Ehdr) header_;
|
||||||
size_t phdr_num_;
|
size_t phdr_num_;
|
||||||
|
|
||||||
void* phdr_mmap_;
|
MappedFileFragment phdr_fragment_;
|
||||||
ElfW(Phdr)* phdr_table_;
|
const ElfW(Phdr)* phdr_table_;
|
||||||
ElfW(Addr) phdr_size_;
|
|
||||||
|
|
||||||
// First page of reserved address space.
|
// First page of reserved address space.
|
||||||
void* load_start_;
|
void* load_start_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user