1c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky/*
2c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Copyright (C) 2016 The Android Open Source Project
3c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky *
4c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Licensed under the Apache License, Version 2.0 (the "License");
5c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * you may not use this file except in compliance with the License.
6c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * You may obtain a copy of the License at
7c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky *
8c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky *      http://www.apache.org/licenses/LICENSE-2.0
9c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky *
10c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Unless required by applicable law or agreed to in writing, software
11c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * distributed under the License is distributed on an "AS IS" BASIS,
12c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * See the License for the specific language governing permissions and
14c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * limitations under the License.
15c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky */
16c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
17c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "elf_debug_writer.h"
18c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
19c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include <vector>
2056da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky#include <unordered_map>
21c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
22d9c90373d640a5e08072cf469c372e24a8c0fc35David Brazdil#include "base/array_ref.h"
23c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/dwarf/dwarf_constants.h"
24c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_compilation_unit.h"
25c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_debug_frame_writer.h"
26c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_debug_info_writer.h"
27c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_debug_line_writer.h"
28c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_debug_loc_writer.h"
29c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_gnu_debugdata_writer.h"
30c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/elf_symtab_writer.h"
31c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/method_debug_info.h"
327452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko#include "linker/elf_builder.h"
33c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "linker/vector_output_stream.h"
34d49012909625c3bf87bf51138fe79315ce1b1bdcAndreas Gampe#include "oat.h"
35c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
36c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckynamespace art {
37c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckynamespace debug {
38c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
39c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckytemplate <typename ElfTypes>
407452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Markovoid WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder,
4132210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                    const DebugInfo& debug_info,
42c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky                    dwarf::CFIFormat cfi_format,
43c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky                    bool write_oat_patches) {
4409c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky  // Write .strtab and .symtab.
4532210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky  WriteDebugSymbols(builder, false /* mini-debug-info */, debug_info);
4609c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky
4709c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky  // Write .debug_frame.
4832210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky  WriteCFISection(builder, debug_info.compiled_methods, cfi_format, write_oat_patches);
49c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
5056da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  // Group the methods into compilation units based on class.
5156da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit;
5232210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky  for (const MethodDebugInfo& mi : debug_info.compiled_methods) {
5309c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky    if (mi.dex_file != nullptr) {
5409c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
5556da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky      ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def];
5609c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      cu.methods.push_back(&mi);
5709c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      // All methods must have the same addressing mode otherwise the min/max below does not work.
5809c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
5909c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      cu.is_code_address_text_relative = mi.is_code_address_text_relative;
6009c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      cu.code_address = std::min(cu.code_address, mi.code_address);
6109c2a6be63337ee060e2d54bd01cf18be7301d29David Srbecky      cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
62c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    }
63c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
64c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
6556da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  // Sort compilation units to make the compiler output deterministic.
6656da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  std::vector<ElfCompilationUnit> compilation_units;
6756da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  compilation_units.reserve(class_to_compilation_unit.size());
6856da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  for (auto& it : class_to_compilation_unit) {
6956da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky    // The .debug_line section requires the methods to be sorted by code address.
7056da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky    std::stable_sort(it.second.methods.begin(),
7156da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                     it.second.methods.end(),
7256da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                     [](const MethodDebugInfo* a, const MethodDebugInfo* b) {
7356da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                         return a->code_address < b->code_address;
7456da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                     });
7556da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky    compilation_units.push_back(std::move(it.second));
7656da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  }
7756da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky  std::sort(compilation_units.begin(),
7856da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky            compilation_units.end(),
7956da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky            [](ElfCompilationUnit& a, ElfCompilationUnit& b) {
8056da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                // Sort by index of the first method within the method_infos array.
8156da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                // This assumes that the order of method_infos is deterministic.
8256da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                // Code address is not good for sorting due to possible duplicates.
8356da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky                return a.methods.front() < b.methods.front();
8456da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky            });
8556da23c6a20e01724b9495443ccab75d4abcaa36David Srbecky
86c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  // Write .debug_line section.
87c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  if (!compilation_units.empty()) {
88c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    ElfDebugLineWriter<ElfTypes> line_writer(builder);
89c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    line_writer.Start();
90c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    for (auto& compilation_unit : compilation_units) {
91c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky      line_writer.WriteCompilationUnit(compilation_unit);
92c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    }
93c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    line_writer.End(write_oat_patches);
94c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
95c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
96c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  // Write .debug_info section.
97c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  if (!compilation_units.empty()) {
98c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    ElfDebugInfoWriter<ElfTypes> info_writer(builder);
99c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    info_writer.Start();
100c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    for (const auto& compilation_unit : compilation_units) {
101c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky      ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
102c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky      cu_writer.Write(compilation_unit);
103c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    }
104c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    info_writer.End(write_oat_patches);
105c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
106c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
107c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
108c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckystd::vector<uint8_t> MakeMiniDebugInfo(
109c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    InstructionSet isa,
1105d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    const InstructionSetFeatures* features,
11132210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    uint64_t text_section_address,
11232210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    size_t text_section_size,
11332210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    uint64_t dex_section_address,
11432210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    size_t dex_section_size,
11532210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    const DebugInfo& debug_info) {
116c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  if (Is64BitInstructionSet(isa)) {
1175d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
1185d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky                                                 features,
11932210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 text_section_address,
12032210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 text_section_size,
12132210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 dex_section_address,
12232210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 dex_section_size,
12332210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 debug_info);
124c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  } else {
1255d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
1265d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky                                                 features,
12732210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 text_section_address,
12832210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 text_section_size,
12932210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 dex_section_address,
13032210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 dex_section_size,
13132210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                                                 debug_info);
132c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
133c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
134c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
135c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckytemplate <typename ElfTypes>
136f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbeckystatic std::vector<uint8_t> MakeElfFileForJITInternal(
137fe736b775c7774bb2f7072e022099ca47dd21a3cDavid Srbecky    InstructionSet isa,
1385d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    const InstructionSetFeatures* features,
139f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky    bool mini_debug_info,
140c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    ArrayRef<const MethodDebugInfo> method_infos) {
141c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  CHECK_GT(method_infos.size(), 0u);
142c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  uint64_t min_address = std::numeric_limits<uint64_t>::max();
143c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  uint64_t max_address = 0;
144c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  for (const MethodDebugInfo& mi : method_infos) {
145c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    CHECK_EQ(mi.is_code_address_text_relative, false);
146c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    min_address = std::min(min_address, mi.code_address);
147c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    max_address = std::max(max_address, mi.code_address + mi.code_size);
148c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  }
14932210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky  DebugInfo debug_info{};
150c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky  debug_info.compiled_methods = method_infos;
151c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  std::vector<uint8_t> buffer;
152c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  buffer.reserve(KB);
1537452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko  linker::VectorOutputStream out("Debug ELF file", &buffer);
1547452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko  std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
1557452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko      new linker::ElfBuilder<ElfTypes>(isa, features, &out));
156c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  // No program headers since the ELF file is not linked and has no allocated sections.
157c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  builder->Start(false /* write_program_headers */);
158f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky  if (mini_debug_info) {
159ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky    if (method_infos.size() > 1) {
160ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      std::vector<uint8_t> mdi = MakeMiniDebugInfo(isa,
161ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   features,
162ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   min_address,
163ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   max_address - min_address,
164ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   /* dex_section_address */ 0,
165ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   /* dex_section_size */ 0,
166ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                                                   debug_info);
167ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      builder->WriteSection(".gnu_debugdata", &mdi);
168ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky    } else {
169ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      // The compression is great help for multiple methods but it is not worth it for a
170ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      // single method due to the overheads so skip the compression here for performance.
171ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
172ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info);
173ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky      WriteCFISection(builder.get(),
174ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                      debug_info.compiled_methods,
175ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                      dwarf::DW_DEBUG_FRAME_FORMAT,
176ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky                      false /* write_oat_paches */);
177ec419db26d96c74e2cb2418db247f9a94ff0d262David Srbecky    }
178f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky  } else {
179c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
180f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky    WriteDebugInfo(builder.get(),
18132210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky                   debug_info,
182f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky                   dwarf::DW_DEBUG_FRAME_FORMAT,
183f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky                   false /* write_oat_patches */);
184f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky  }
185c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  builder->End();
186c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  CHECK(builder->Good());
18793205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Marko  return buffer;
188c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
189c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
190f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbeckystd::vector<uint8_t> MakeElfFileForJIT(
191fe736b775c7774bb2f7072e022099ca47dd21a3cDavid Srbecky    InstructionSet isa,
192fe736b775c7774bb2f7072e022099ca47dd21a3cDavid Srbecky    const InstructionSetFeatures* features,
193f4886df5e72fa21eddfc4cc7860f4154929b3380David Srbecky    bool mini_debug_info,
194c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    ArrayRef<const MethodDebugInfo> method_infos) {
195c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  if (Is64BitInstructionSet(isa)) {
196c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_infos);
197c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  } else {
198c684f337eae6bd3d77fa44cb568d2bab113e4ceeDavid Srbecky    return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_infos);
199c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
200c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
201c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
202c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckytemplate <typename ElfTypes>
20393205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Markostatic std::vector<uint8_t> WriteDebugElfFileForClassesInternal(
204fe736b775c7774bb2f7072e022099ca47dd21a3cDavid Srbecky    InstructionSet isa,
2055d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    const InstructionSetFeatures* features,
2065d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    const ArrayRef<mirror::Class*>& types)
207bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe    REQUIRES_SHARED(Locks::mutator_lock_) {
208c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  std::vector<uint8_t> buffer;
209c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  buffer.reserve(KB);
2107452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko  linker::VectorOutputStream out("Debug ELF file", &buffer);
2117452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko  std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
2127452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko      new linker::ElfBuilder<ElfTypes>(isa, features, &out));
213c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  // No program headers since the ELF file is not linked and has no allocated sections.
214c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  builder->Start(false /* write_program_headers */);
215c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
216c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  info_writer.Start();
217c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
218c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  cu_writer.Write(types);
219c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  info_writer.End(false /* write_oat_patches */);
220c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
221c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  builder->End();
222c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  CHECK(builder->Good());
22393205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Marko  return buffer;
224c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
225c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
22693205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Markostd::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa,
22793205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Marko                                                 const InstructionSetFeatures* features,
22893205e395f777c1dd81d3f164cf9a4aec4bde45fVladimir Marko                                                 const ArrayRef<mirror::Class*>& types) {
229c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  if (Is64BitInstructionSet(isa)) {
2305d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, features, types);
231c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  } else {
2325d8112029d0e085c5a0099257daa4c7e29c12310David Srbecky    return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, features, types);
233c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky  }
234c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}
235c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
236c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// Explicit instantiations
237c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckytemplate void WriteDebugInfo<ElfTypes32>(
2387452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko    linker::ElfBuilder<ElfTypes32>* builder,
23932210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    const DebugInfo& debug_info,
240c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    dwarf::CFIFormat cfi_format,
241c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    bool write_oat_patches);
242c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckytemplate void WriteDebugInfo<ElfTypes64>(
2437452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko    linker::ElfBuilder<ElfTypes64>* builder,
24432210b9f8c30e202e275764200315fe26f22f34cDavid Srbecky    const DebugInfo& debug_info,
245c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    dwarf::CFIFormat cfi_format,
246c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky    bool write_oat_patches);
247c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky
248c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}  // namespace debug
249c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}  // namespace art
250