elf_writer_quick.cc revision 86e4278d5edc3685465b8846dcb17efa83c86d75
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 "driver/compiler_options.h"
27#include "dwarf/method_debug_info.h"
28#include "elf.h"
29#include "elf_builder.h"
30#include "elf_utils.h"
31#include "elf_writer_debug.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 "utils.h"
37
38namespace art {
39
40// .eh_frame and .debug_frame are almost identical.
41// Except for some minor formatting differences, the main difference
42// is that .eh_frame is allocated within the running program because
43// it is used by C++ exception handling (which we do not use so we
44// can choose either).  C++ compilers generally tend to use .eh_frame
45// because if they need it sometimes, they might as well always use it.
46// Let's use .debug_frame because it is easier to strip or compress.
47constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
48
49template <typename ElfTypes>
50class ElfWriterQuick FINAL : public ElfWriter {
51 public:
52  ElfWriterQuick(InstructionSet instruction_set,
53                 const CompilerOptions* compiler_options,
54                 File* elf_file);
55  ~ElfWriterQuick();
56
57  void Start() OVERRIDE;
58  OutputStream* StartRoData() OVERRIDE;
59  void EndRoData(OutputStream* rodata) OVERRIDE;
60  OutputStream* StartText() OVERRIDE;
61  void EndText(OutputStream* text) OVERRIDE;
62  void SetBssSize(size_t bss_size) OVERRIDE;
63  void WriteDynamicSection() OVERRIDE;
64  void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE;
65  void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE;
66  bool End() OVERRIDE;
67
68  virtual OutputStream* GetStream() OVERRIDE;
69
70  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
71                               std::vector<uint8_t>* buffer);
72
73 private:
74  const CompilerOptions* const compiler_options_;
75  File* const elf_file_;
76  std::unique_ptr<BufferedOutputStream> output_stream_;
77  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
78
79  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
80};
81
82std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
83                                                const CompilerOptions* compiler_options,
84                                                File* elf_file) {
85  if (Is64BitInstructionSet(instruction_set)) {
86    return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file);
87  } else {
88    return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file);
89  }
90}
91
92template <typename ElfTypes>
93ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
94                                         const CompilerOptions* compiler_options,
95                                         File* elf_file)
96    : ElfWriter(),
97      compiler_options_(compiler_options),
98      elf_file_(elf_file),
99      output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))),
100      builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {}
101
102template <typename ElfTypes>
103ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
104
105template <typename ElfTypes>
106void ElfWriterQuick<ElfTypes>::Start() {
107  builder_->Start();
108}
109
110template <typename ElfTypes>
111OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
112  auto* rodata = builder_->GetRoData();
113  rodata->Start();
114  return rodata;
115}
116
117template <typename ElfTypes>
118void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
119  CHECK_EQ(builder_->GetRoData(), rodata);
120  builder_->GetRoData()->End();
121}
122
123template <typename ElfTypes>
124OutputStream* ElfWriterQuick<ElfTypes>::StartText() {
125  auto* text = builder_->GetText();
126  text->Start();
127  return text;
128}
129
130template <typename ElfTypes>
131void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
132  CHECK_EQ(builder_->GetText(), text);
133  builder_->GetText()->End();
134}
135
136template <typename ElfTypes>
137void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) {
138  auto* bss = builder_->GetBss();
139  if (bss_size != 0u) {
140    bss->Start();
141    bss->SetSize(bss_size);
142    bss->End();
143  }
144}
145
146template <typename ElfTypes>
147void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
148  builder_->WriteDynamicSection(elf_file_->GetPath());
149}
150
151template <typename ElfTypes>
152void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
153    const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
154  if (compiler_options_->GetGenerateDebugInfo()) {
155    dwarf::WriteDebugInfo(builder_.get(), /* write_types */ true, method_infos, kCFIFormat);
156  }
157}
158
159template <typename ElfTypes>
160void ElfWriterQuick<ElfTypes>::WritePatchLocations(
161    const ArrayRef<const uintptr_t>& patch_locations) {
162  // Add relocation section for .text.
163  if (compiler_options_->GetIncludePatchInformation()) {
164    // Note that ElfWriter::Fixup will be called regardless and therefore
165    // we need to include oat_patches for debug sections unconditionally.
166    builder_->WritePatches(".text.oat_patches", patch_locations);
167  }
168}
169
170template <typename ElfTypes>
171bool ElfWriterQuick<ElfTypes>::End() {
172  builder_->End();
173
174  return builder_->Good();
175}
176
177template <typename ElfTypes>
178OutputStream* ElfWriterQuick<ElfTypes>::GetStream() {
179  return builder_->GetStream();
180}
181
182// Explicit instantiations
183template class ElfWriterQuick<ElfTypes32>;
184template class ElfWriterQuick<ElfTypes64>;
185
186}  // namespace art
187