elf_writer_quick.cc revision 5d8112029d0e085c5a0099257daa4c7e29c12310
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#include <unordered_set>
21
22#include "base/casts.h"
23#include "base/logging.h"
24#include "base/stl_util.h"
25#include "compiled_method.h"
26#include "debug/elf_debug_writer.h"
27#include "debug/method_debug_info.h"
28#include "driver/compiler_options.h"
29#include "elf.h"
30#include "elf_builder.h"
31#include "elf_utils.h"
32#include "globals.h"
33#include "leb128.h"
34#include "linker/buffered_output_stream.h"
35#include "linker/file_output_stream.h"
36#include "thread-inl.h"
37#include "thread_pool.h"
38#include "utils.h"
39
40namespace art {
41
42// .eh_frame and .debug_frame are almost identical.
43// Except for some minor formatting differences, the main difference
44// is that .eh_frame is allocated within the running program because
45// it is used by C++ exception handling (which we do not use so we
46// can choose either).  C++ compilers generally tend to use .eh_frame
47// because if they need it sometimes, they might as well always use it.
48// Let's use .debug_frame because it is easier to strip or compress.
49constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
50
51class DebugInfoTask : public Task {
52 public:
53  DebugInfoTask(InstructionSet isa,
54                const InstructionSetFeatures* features,
55                size_t rodata_section_size,
56                size_t text_section_size,
57                const ArrayRef<const debug::MethodDebugInfo>& method_infos)
58      : isa_(isa),
59        instruction_set_features_(features),
60        rodata_section_size_(rodata_section_size),
61        text_section_size_(text_section_size),
62        method_infos_(method_infos) {
63  }
64
65  void Run(Thread*) {
66    result_ = debug::MakeMiniDebugInfo(isa_,
67                                       instruction_set_features_,
68                                       rodata_section_size_,
69                                       text_section_size_,
70                                       method_infos_);
71  }
72
73  std::vector<uint8_t>* GetResult() {
74    return &result_;
75  }
76
77 private:
78  InstructionSet isa_;
79  const InstructionSetFeatures* instruction_set_features_;
80  size_t rodata_section_size_;
81  size_t text_section_size_;
82  const ArrayRef<const debug::MethodDebugInfo>& method_infos_;
83  std::vector<uint8_t> result_;
84};
85
86template <typename ElfTypes>
87class ElfWriterQuick FINAL : public ElfWriter {
88 public:
89  ElfWriterQuick(InstructionSet instruction_set,
90                 const InstructionSetFeatures* features,
91                 const CompilerOptions* compiler_options,
92                 File* elf_file);
93  ~ElfWriterQuick();
94
95  void Start() OVERRIDE;
96  void SetLoadedSectionSizes(size_t rodata_size, size_t text_size, size_t bss_size) OVERRIDE;
97  void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
98  OutputStream* StartRoData() OVERRIDE;
99  void EndRoData(OutputStream* rodata) OVERRIDE;
100  OutputStream* StartText() OVERRIDE;
101  void EndText(OutputStream* text) OVERRIDE;
102  void WriteDynamicSection() OVERRIDE;
103  void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
104  void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE;
105  bool End() OVERRIDE;
106
107  virtual OutputStream* GetStream() OVERRIDE;
108
109  size_t GetLoadedSize() OVERRIDE;
110
111  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
112                               std::vector<uint8_t>* buffer);
113
114 private:
115  const InstructionSetFeatures* instruction_set_features_;
116  const CompilerOptions* const compiler_options_;
117  File* const elf_file_;
118  size_t rodata_size_;
119  size_t text_size_;
120  size_t bss_size_;
121  std::unique_ptr<BufferedOutputStream> output_stream_;
122  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
123  std::unique_ptr<DebugInfoTask> debug_info_task_;
124  std::unique_ptr<ThreadPool> debug_info_thread_pool_;
125
126  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
127};
128
129std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
130                                                const InstructionSetFeatures* features,
131                                                const CompilerOptions* compiler_options,
132                                                File* elf_file) {
133  if (Is64BitInstructionSet(instruction_set)) {
134    return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set,
135                                                  features,
136                                                  compiler_options,
137                                                  elf_file);
138  } else {
139    return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set,
140                                                  features,
141                                                  compiler_options,
142                                                  elf_file);
143  }
144}
145
146template <typename ElfTypes>
147ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
148                                         const InstructionSetFeatures* features,
149                                         const CompilerOptions* compiler_options,
150                                         File* elf_file)
151    : ElfWriter(),
152      instruction_set_features_(features),
153      compiler_options_(compiler_options),
154      elf_file_(elf_file),
155      rodata_size_(0u),
156      text_size_(0u),
157      bss_size_(0u),
158      output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))),
159      builder_(new ElfBuilder<ElfTypes>(instruction_set, features, output_stream_.get())) {}
160
161template <typename ElfTypes>
162ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
163
164template <typename ElfTypes>
165void ElfWriterQuick<ElfTypes>::Start() {
166  builder_->Start();
167}
168
169template <typename ElfTypes>
170void ElfWriterQuick<ElfTypes>::SetLoadedSectionSizes(size_t rodata_size,
171                                                     size_t text_size,
172                                                     size_t bss_size) {
173  DCHECK_EQ(rodata_size_, 0u);
174  rodata_size_ = rodata_size;
175  DCHECK_EQ(text_size_, 0u);
176  text_size_ = text_size;
177  DCHECK_EQ(bss_size_, 0u);
178  bss_size_ = bss_size;
179  builder_->PrepareDynamicSection(elf_file_->GetPath(), rodata_size_, text_size_, bss_size_);
180}
181
182template <typename ElfTypes>
183OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
184  auto* rodata = builder_->GetRoData();
185  rodata->Start();
186  return rodata;
187}
188
189template <typename ElfTypes>
190void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
191  CHECK_EQ(builder_->GetRoData(), rodata);
192  builder_->GetRoData()->End();
193}
194
195template <typename ElfTypes>
196OutputStream* ElfWriterQuick<ElfTypes>::StartText() {
197  auto* text = builder_->GetText();
198  text->Start();
199  return text;
200}
201
202template <typename ElfTypes>
203void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
204  CHECK_EQ(builder_->GetText(), text);
205  builder_->GetText()->End();
206}
207
208template <typename ElfTypes>
209void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
210  if (bss_size_ != 0u) {
211    builder_->GetBss()->WriteNoBitsSection(bss_size_);
212  }
213  builder_->WriteDynamicSection();
214}
215
216template <typename ElfTypes>
217void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(
218    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
219  if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) {
220    // Prepare the mini-debug-info in background while we do other I/O.
221    Thread* self = Thread::Current();
222    debug_info_task_ = std::unique_ptr<DebugInfoTask>(
223        new DebugInfoTask(builder_->GetIsa(),
224                          instruction_set_features_,
225                          rodata_size_,
226                          text_size_,
227                          method_infos));
228    debug_info_thread_pool_ = std::unique_ptr<ThreadPool>(
229        new ThreadPool("Mini-debug-info writer", 1));
230    debug_info_thread_pool_->AddTask(self, debug_info_task_.get());
231    debug_info_thread_pool_->StartWorkers(self);
232  }
233}
234
235template <typename ElfTypes>
236void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
237    const ArrayRef<const debug::MethodDebugInfo>& method_infos) {
238  if (!method_infos.empty()) {
239    if (compiler_options_->GetGenerateDebugInfo()) {
240      // Generate all the debug information we can.
241      debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */);
242    }
243    if (compiler_options_->GetGenerateMiniDebugInfo()) {
244      // Wait for the mini-debug-info generation to finish and write it to disk.
245      Thread* self = Thread::Current();
246      DCHECK(debug_info_thread_pool_ != nullptr);
247      debug_info_thread_pool_->Wait(self, true, false);
248      builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult());
249    }
250  }
251}
252
253template <typename ElfTypes>
254void ElfWriterQuick<ElfTypes>::WritePatchLocations(
255    const ArrayRef<const uintptr_t>& patch_locations) {
256  // Add relocation section for .text.
257  if (compiler_options_->GetIncludePatchInformation()) {
258    // Note that ElfWriter::Fixup will be called regardless and therefore
259    // we need to include oat_patches for debug sections unconditionally.
260    builder_->WritePatches(".text.oat_patches", patch_locations);
261  }
262}
263
264template <typename ElfTypes>
265bool ElfWriterQuick<ElfTypes>::End() {
266  builder_->End();
267
268  return builder_->Good();
269}
270
271template <typename ElfTypes>
272OutputStream* ElfWriterQuick<ElfTypes>::GetStream() {
273  return builder_->GetStream();
274}
275
276template <typename ElfTypes>
277size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() {
278  return builder_->GetLoadedSize();
279}
280
281// Explicit instantiations
282template class ElfWriterQuick<ElfTypes32>;
283template class ElfWriterQuick<ElfTypes64>;
284
285}  // namespace art
286