1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CRAZY_LINKER_ELF_LOADER_H
6#define CRAZY_LINKER_ELF_LOADER_H
7
8#include "crazy_linker_error.h"
9#include "crazy_linker_system.h"  // For ScopedFileDescriptor
10#include "elf_traits.h"
11
12namespace crazy {
13
14// Helper class used to load an ELF binary in memory.
15//
16// Note that this doesn't not perform any relocation, the purpose
17// of this class is strictly to map all loadable segments from the
18// file to their correct location.
19//
20class ElfLoader {
21 public:
22  ElfLoader();
23  ~ElfLoader();
24
25  // Try to load a library at a given address. On failure, this will
26  // update the linker error message and returns false.
27  //
28  // |lib_path| is the full library path, and |wanted_address| should
29  // be the desired load address, or 0 to enable randomization.
30  //
31  // |file_offset| is an offset in the file where the ELF header will
32  // be looked for.
33  //
34  // |wanted_address| is the wanted load address (of the first loadable
35  // segment), or 0 to enable randomization.
36  //
37  // On success, the library's loadable segments will be mapped in
38  // memory with their original protection. However, no further processing
39  // will be performed.
40  //
41  // On failure, returns false and assign an error message to |error|.
42  bool LoadAt(const char* lib_path,
43              off_t file_offset,
44              uintptr_t wanted_address,
45              Error* error);
46
47  // Only call the following functions after a succesfull LoadAt() call.
48
49  size_t phdr_count() { return phdr_num_; }
50  ELF::Addr load_start() { return reinterpret_cast<ELF::Addr>(load_start_); }
51  ELF::Addr load_size() { return load_size_; }
52  ELF::Addr load_bias() { return load_bias_; }
53  const ELF::Phdr* loaded_phdr() { return loaded_phdr_; }
54
55 private:
56  FileDescriptor fd_;
57  const char* path_;
58
59  ELF::Ehdr header_;
60  size_t phdr_num_;
61
62  void* phdr_mmap_;  // temporary copy of the program header.
63  ELF::Phdr* phdr_table_;
64  ELF::Addr phdr_size_;  // and its size.
65
66  off_t file_offset_;
67  void* wanted_load_address_;
68  void* load_start_;     // First page of reserved address space.
69  ELF::Addr load_size_;  // Size in bytes of reserved address space.
70  ELF::Addr load_bias_;  // load_bias, add this value to all "vaddr"
71                         // values in the library to get the corresponding
72                         // memory address.
73
74  const ELF::Phdr* loaded_phdr_;  // points to the loaded program header.
75
76  // Individual steps used by ::LoadAt()
77  bool ReadElfHeader(Error* error);
78  bool ReadProgramHeader(Error* error);
79  bool ReserveAddressSpace(Error* error);
80  bool LoadSegments(Error* error);
81  bool FindPhdr(Error* error);
82  bool CheckPhdr(ELF::Addr, Error* error);
83};
84
85}  // namespace crazy
86
87#endif  // CRAZY_LINKER_ELF_LOADER_H
88