148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Copyright (c) 2013 The Chromium Authors. All rights reserved. 248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Use of this source code is governed by a BSD-style license that can be 348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// found in the LICENSE file. 448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#ifndef CRAZY_LINKER_ELF_LOADER_H 648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#define CRAZY_LINKER_ELF_LOADER_H 748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_error.h" 948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "crazy_linker_system.h" // For ScopedFileDescriptor 1048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#include "elf_traits.h" 1148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 1248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnernamespace crazy { 1348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 1448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Helper class used to load an ELF binary in memory. 1548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 1648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// Note that this doesn't not perform any relocation, the purpose 1748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// of this class is strictly to map all loadable segments from the 1848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// file to their correct location. 1948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner// 2048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turnerclass ElfLoader { 2148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner public: 2248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ElfLoader(); 2348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ~ElfLoader(); 2448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 2548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // Try to load a library at a given address. On failure, this will 2648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // update the linker error message and returns false. 2748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // 2848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // |lib_path| is the full library path, and |wanted_address| should 2948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // be the desired load address, or 0 to enable randomization. 3048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // 3148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // |file_offset| is an offset in the file where the ELF header will 3248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // be looked for. 3348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // 3448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // |wanted_address| is the wanted load address (of the first loadable 3548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // segment), or 0 to enable randomization. 3648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // 3748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // On success, the library's loadable segments will be mapped in 3848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // memory with their original protection. However, no further processing 3948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // will be performed. 4048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // 4148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // On failure, returns false and assign an error message to |error|. 4248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool LoadAt(const char* lib_path, 4348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner off_t file_offset, 4448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner uintptr_t wanted_address, 4548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner Error* error); 4648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 4748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // Only call the following functions after a succesfull LoadAt() call. 4848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 4948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t phdr_count() { return phdr_num_; } 5048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr load_start() { return reinterpret_cast<ELF::Addr>(load_start_); } 5148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr load_size() { return load_size_; } 5248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr load_bias() { return load_bias_; } 5348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const ELF::Phdr* loaded_phdr() { return loaded_phdr_; } 5448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 5548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner private: 5648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner FileDescriptor fd_; 5748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const char* path_; 5848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 5948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Ehdr header_; 6048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner size_t phdr_num_; 6148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 6248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* phdr_mmap_; // temporary copy of the program header. 6348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Phdr* phdr_table_; 6448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr phdr_size_; // and its size. 6548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 6648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner off_t file_offset_; 6748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* wanted_load_address_; 6848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner void* load_start_; // First page of reserved address space. 6948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr load_size_; // Size in bytes of reserved address space. 7048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner ELF::Addr load_bias_; // load_bias, add this value to all "vaddr" 7148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // values in the library to get the corresponding 7248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // memory address. 7348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 7448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner const ELF::Phdr* loaded_phdr_; // points to the loaded program header. 7548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 7648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner // Individual steps used by ::LoadAt() 7748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool ReadElfHeader(Error* error); 7848cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool ReadProgramHeader(Error* error); 7948cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool ReserveAddressSpace(Error* error); 8048cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool LoadSegments(Error* error); 8148cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool FindPhdr(Error* error); 8248cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner bool CheckPhdr(ELF::Addr, Error* error); 8348cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner}; 8448cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 8548cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner} // namespace crazy 8648cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner 8748cdce8c044f6e7d11aa2b5eb97635c922e0bc58David 'Digit' Turner#endif // CRAZY_LINKER_ELF_LOADER_H 88