elf_writer_quick.cc revision 8dc7324da5bd0f2afd2ab558ab04882329a61fe8
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "elf_writer_quick.h"
18
19#include <unordered_map>
20
21#include "base/logging.h"
22#include "base/unix_file/fd_file.h"
23#include "buffered_output_stream.h"
24#include "compiled_method.h"
25#include "dex_file-inl.h"
26#include "driver/compiler_driver.h"
27#include "driver/compiler_options.h"
28#include "elf_builder.h"
29#include "elf_file.h"
30#include "elf_utils.h"
31#include "elf_writer_debug.h"
32#include "file_output_stream.h"
33#include "globals.h"
34#include "leb128.h"
35#include "oat.h"
36#include "oat_writer.h"
37#include "utils.h"
38
39namespace art {
40
41template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
42          typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
43          typename Elf_Phdr, typename Elf_Shdr>
44bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
45  Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file,
46                            OatWriter* oat_writer,
47                            const std::vector<const DexFile*>& dex_files,
48                            const std::string& android_root,
49                            bool is_host,
50                            const CompilerDriver& driver) {
51  ElfWriterQuick elf_writer(driver, elf_file);
52  return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
53}
54
55class OatWriterWrapper FINAL : public CodeOutput {
56 public:
57  explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {}
58
59  void SetCodeOffset(size_t offset) {
60    oat_writer_->SetOatDataOffset(offset);
61  }
62  bool Write(OutputStream* out) OVERRIDE {
63    return oat_writer_->Write(out);
64  }
65 private:
66  OatWriter* const oat_writer_;
67};
68
69template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
70          typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
71          typename Elf_Phdr, typename Elf_Shdr>
72static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
73                              ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
74                                         Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
75                              OatWriter* oat_writer);
76
77// Encode patch locations in .oat_patches format.
78template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
79          typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
80          typename Elf_Phdr, typename Elf_Shdr>
81void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, Elf_Sym, Elf_Ehdr,
82  Elf_Phdr, Elf_Shdr>::EncodeOatPatches(const OatWriter::PatchLocationsMap& sections,
83                                        std::vector<uint8_t>* buffer) {
84  for (const auto& section : sections) {
85    const std::string& name = section.first;
86    std::vector<uintptr_t>* locations = section.second.get();
87    DCHECK(!name.empty());
88    std::sort(locations->begin(), locations->end());
89    // Reserve buffer space - guess 2 bytes per ULEB128.
90    buffer->reserve(buffer->size() + name.size() + locations->size() * 2);
91    // Write null-terminated section name.
92    const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str());
93    buffer->insert(buffer->end(), name_data, name_data + name.size() + 1);
94    // Write placeholder for data length.
95    size_t length_pos = buffer->size();
96    EncodeUnsignedLeb128(buffer, UINT32_MAX);
97    // Write LEB128 encoded list of advances (deltas between consequtive addresses).
98    size_t data_pos = buffer->size();
99    uintptr_t address = 0;  // relative to start of section.
100    for (uintptr_t location : *locations) {
101      DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations";
102      EncodeUnsignedLeb128(buffer, location - address);
103      address = location;
104    }
105    // Update length.
106    UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos);
107  }
108  buffer->push_back(0);  // End of sections.
109}
110
111template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
112          typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
113          typename Elf_Phdr, typename Elf_Shdr>
114bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
115  Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer,
116                           const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
117                           const std::string& android_root_unused ATTRIBUTE_UNUSED,
118                           bool is_host_unused ATTRIBUTE_UNUSED) {
119  constexpr bool debug = false;
120  const OatHeader& oat_header = oat_writer->GetOatHeader();
121  Elf_Word oat_data_size = oat_header.GetExecutableOffset();
122  uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size;
123  uint32_t oat_bss_size = oat_writer->GetBssSize();
124
125  OatWriterWrapper wrapper(oat_writer);
126
127  std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
128                             Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder(
129      new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
130                     Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>(
131          &wrapper,
132          elf_file_,
133          compiler_driver_->GetInstructionSet(),
134          0,
135          oat_data_size,
136          oat_data_size,
137          oat_exec_size,
138          RoundUp(oat_data_size + oat_exec_size, kPageSize),
139          oat_bss_size,
140          compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(),
141          debug));
142
143  if (!builder->Init()) {
144    return false;
145  }
146
147  if (compiler_driver_->GetCompilerOptions().GetIncludeCFI() &&
148      !oat_writer->GetMethodDebugInfo().empty()) {
149    ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame(
150        ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0);
151    dwarf::WriteEhFrame(compiler_driver_, oat_writer,
152                        builder->GetTextBuilder().GetSection()->sh_addr,
153                        eh_frame.GetBuffer());
154    builder->RegisterRawSection(eh_frame);
155  }
156
157  if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols() &&
158      !oat_writer->GetMethodDebugInfo().empty()) {
159    WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer);
160  }
161
162  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
163      // ElfWriter::Fixup will be called regardless and it needs to be able
164      // to patch debug sections so we have to include patches for them.
165      compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
166    ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches(
167        ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, 1, 0);
168    EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
169    builder->RegisterRawSection(oat_patches);
170  }
171
172  return builder->Write();
173}
174
175template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr,
176          typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr,
177          typename Elf_Phdr, typename Elf_Shdr>
178// Do not inline to avoid Clang stack frame problems. b/18738594
179NO_INLINE
180static void WriteDebugSymbols(const CompilerDriver* compiler_driver,
181                              ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn,
182                                         Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder,
183                              OatWriter* oat_writer) {
184  // Iterate over the compiled methods.
185  const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
186  ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
187      builder->GetSymtabBuilder();
188  for (auto it = method_info.begin(); it != method_info.end(); ++it) {
189    std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true);
190    if (it->deduped_) {
191      // TODO We should place the DEDUPED tag on the first instance of a deduplicated symbol
192      // so that it will show up in a debuggerd crash report.
193      name += " [ DEDUPED ]";
194    }
195
196    uint32_t low_pc = it->low_pc_;
197    // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
198    low_pc += it->compiled_method_->CodeDelta();
199    symtab->AddSymbol(name, &builder->GetTextBuilder(), low_pc,
200                      true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
201
202    // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
203    // instructions, so that disassembler tools can correctly disassemble.
204    if (it->compiled_method_->GetInstructionSet() == kThumb2) {
205      symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
206                        0, STB_LOCAL, STT_NOTYPE);
207    }
208  }
209
210  typedef ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> Section;
211  Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
212  Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
213  Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
214  Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
215
216  dwarf::WriteDebugSections(compiler_driver,
217                            oat_writer,
218                            builder->GetTextBuilder().GetSection()->sh_addr,
219                            debug_info.GetBuffer(),
220                            debug_abbrev.GetBuffer(),
221                            debug_str.GetBuffer(),
222                            debug_line.GetBuffer());
223
224  builder->RegisterRawSection(debug_info);
225  builder->RegisterRawSection(debug_abbrev);
226  builder->RegisterRawSection(debug_str);
227  builder->RegisterRawSection(debug_line);
228}
229
230// Explicit instantiations
231template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
232                              Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>;
233template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn,
234                              Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>;
235
236}  // namespace art
237