bionic: Introduce ElfReader::ReadPadSegmentNote()
ReadPadSegmentNote() finds the elf note of type NT_ANDROID_TYPE_PAD_SEGMENT and checks that the desc value is 1, to decided whether the LOAD segment mappings should be extended (padded) to avoid gaps. Cache the result of this operation in ElfReader and soinfo for use in the subsequent patch which handles the extension of the segment mappings. Test: atest -c linker-unit-tests [Later patch] Test: m && launch_cvd Bug: 316403210 Change-Id: I32c05cce741d221c3f92835ea09d932c40bdf8b1 Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
This commit is contained in:
parent
f0050fb015
commit
377f0b9138
4 changed files with 58 additions and 1 deletions
|
@ -639,6 +639,7 @@ class LoadTask {
|
|||
si_->phdr = elf_reader.loaded_phdr();
|
||||
si_->set_gap_start(elf_reader.gap_start());
|
||||
si_->set_gap_size(elf_reader.gap_size());
|
||||
si_->set_should_pad_segments(elf_reader.should_pad_segments());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@
|
|||
#include "linker_debug.h"
|
||||
#include "linker_utils.h"
|
||||
|
||||
#include "private/bionic_asm_note.h"
|
||||
#include "private/CFIShadow.h" // For kLibraryAlignment
|
||||
#include "private/elf_note.h"
|
||||
|
||||
static int GetTargetElfMachine() {
|
||||
#if defined(__arm__)
|
||||
|
@ -163,7 +165,8 @@ bool ElfReader::Read(const char* name, int fd, off64_t file_offset, off64_t file
|
|||
VerifyElfHeader() &&
|
||||
ReadProgramHeaders() &&
|
||||
ReadSectionHeaders() &&
|
||||
ReadDynamicSection()) {
|
||||
ReadDynamicSection() &&
|
||||
ReadPadSegmentNote()) {
|
||||
did_read_ = true;
|
||||
}
|
||||
|
||||
|
@ -694,6 +697,46 @@ bool ElfReader::ReserveAddressSpace(address_space_params* address_space) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Find the ELF note of type NT_ANDROID_TYPE_PAD_SEGMENT and check that the desc value is 1.
|
||||
bool ElfReader::ReadPadSegmentNote() {
|
||||
// The ELF can have multiple PT_NOTE's, check them all
|
||||
for (size_t i = 0; i < phdr_num_; ++i) {
|
||||
const ElfW(Phdr)* phdr = &phdr_table_[i];
|
||||
|
||||
if (phdr->p_type != PT_NOTE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// note_fragment is scoped to within the loop so that there is
|
||||
// at most 1 PT_NOTE mapped at anytime during this search.
|
||||
MappedFileFragment note_fragment;
|
||||
if (!note_fragment.Map(fd_, file_offset_, phdr->p_offset, phdr->p_memsz)) {
|
||||
DL_ERR("\"%s\" note mmap failed: %s", name_.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const ElfW(Nhdr)* note_hdr = nullptr;
|
||||
const char* note_desc = nullptr;
|
||||
if (!__get_elf_note(NT_ANDROID_TYPE_PAD_SEGMENT, "Android",
|
||||
reinterpret_cast<ElfW(Addr)>(note_fragment.data()),
|
||||
phdr, ¬e_hdr, ¬e_desc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (note_hdr->n_descsz != sizeof(ElfW(Word))) {
|
||||
DL_ERR("\"%s\" NT_ANDROID_TYPE_PAD_SEGMENT note has unexpected n_descsz: %u",
|
||||
name_.c_str(), reinterpret_cast<unsigned int>(note_hdr->n_descsz));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1 == enabled, 0 == disabled
|
||||
should_pad_segments_ = *reinterpret_cast<const ElfW(Word)*>(note_desc) == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElfReader::LoadSegments() {
|
||||
for (size_t i = 0; i < phdr_num_; ++i) {
|
||||
const ElfW(Phdr)* phdr = &phdr_table_[i];
|
||||
|
|
|
@ -58,6 +58,7 @@ class ElfReader {
|
|||
const char* get_string(ElfW(Word) index) const;
|
||||
bool is_mapped_by_caller() const { return mapped_by_caller_; }
|
||||
ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; }
|
||||
bool should_pad_segments() const { return should_pad_segments_; }
|
||||
|
||||
private:
|
||||
bool ReadElfHeader();
|
||||
|
@ -65,6 +66,7 @@ class ElfReader {
|
|||
bool ReadProgramHeaders();
|
||||
bool ReadSectionHeaders();
|
||||
bool ReadDynamicSection();
|
||||
bool ReadPadSegmentNote();
|
||||
bool ReserveAddressSpace(address_space_params* address_space);
|
||||
bool LoadSegments();
|
||||
bool FindPhdr();
|
||||
|
@ -113,6 +115,9 @@ class ElfReader {
|
|||
// Is map owned by the caller
|
||||
bool mapped_by_caller_;
|
||||
|
||||
// Pad gaps between segments when memory mapping?
|
||||
bool should_pad_segments_ = false;
|
||||
|
||||
// Only used by AArch64 at the moment.
|
||||
GnuPropertySection note_gnu_property_ __unused;
|
||||
};
|
||||
|
|
|
@ -364,6 +364,11 @@ struct soinfo {
|
|||
bool memtag_heap() const { return memtag_dynamic_entries()->memtag_heap; }
|
||||
bool memtag_stack() const { return memtag_dynamic_entries()->memtag_stack; }
|
||||
|
||||
void set_should_pad_segments(bool should_pad_segments) {
|
||||
should_pad_segments_ = should_pad_segments;
|
||||
}
|
||||
bool should_pad_segments() const { return should_pad_segments_; }
|
||||
|
||||
private:
|
||||
bool is_image_linked() const;
|
||||
void set_image_linked();
|
||||
|
@ -449,6 +454,9 @@ struct soinfo {
|
|||
|
||||
// version >= 7
|
||||
memtag_dynamic_entries_t memtag_dynamic_entries_;
|
||||
|
||||
// Pad gaps between segments when memory mapping?
|
||||
bool should_pad_segments_ = false;
|
||||
};
|
||||
|
||||
// This function is used by dlvsym() to calculate hash of sym_ver
|
||||
|
|
Loading…
Reference in a new issue