blob: baf8643e9be62297f10982ab6b353161a2e4c69a [file] [log] [blame]
David Srbeckyc5bfa972016-02-05 15:49:10 +00001/*
2 * Copyright (C) 2016 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_debug_writer.h"
18
David Srbeckybe50f9a2018-12-05 10:48:42 +000019#include <type_traits>
David Srbecky56da23c2017-09-08 19:59:15 +010020#include <unordered_map>
David Srbeckybe50f9a2018-12-05 10:48:42 +000021#include <vector>
David Srbeckyc5bfa972016-02-05 15:49:10 +000022
David Brazdild9c90372016-09-14 16:53:55 +010023#include "base/array_ref.h"
David Srbeckyc5bfa972016-02-05 15:49:10 +000024#include "debug/dwarf/dwarf_constants.h"
25#include "debug/elf_compilation_unit.h"
26#include "debug/elf_debug_frame_writer.h"
27#include "debug/elf_debug_info_writer.h"
28#include "debug/elf_debug_line_writer.h"
29#include "debug/elf_debug_loc_writer.h"
David Srbeckyc5bfa972016-02-05 15:49:10 +000030#include "debug/elf_symtab_writer.h"
31#include "debug/method_debug_info.h"
David Srbecky154c57f2018-06-03 12:00:27 +010032#include "debug/xz_utils.h"
David Srbeckybe50f9a2018-12-05 10:48:42 +000033#include "elf.h"
Vladimir Marko74527972016-11-29 15:57:32 +000034#include "linker/elf_builder.h"
David Srbeckyc5bfa972016-02-05 15:49:10 +000035#include "linker/vector_output_stream.h"
Andreas Gamped4901292017-05-30 18:41:34 -070036#include "oat.h"
David Srbeckyc5bfa972016-02-05 15:49:10 +000037
38namespace art {
39namespace debug {
40
David Srbeckybe50f9a2018-12-05 10:48:42 +000041using ElfRuntimeTypes = std::conditional<sizeof(void*) == 4, ElfTypes32, ElfTypes64>::type;
42
David Srbeckyc5bfa972016-02-05 15:49:10 +000043template <typename ElfTypes>
Vladimir Marko74527972016-11-29 15:57:32 +000044void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder,
David Srbecky32210b92017-12-04 14:39:21 +000045 const DebugInfo& debug_info,
David Srbeckyc5bfa972016-02-05 15:49:10 +000046 dwarf::CFIFormat cfi_format,
47 bool write_oat_patches) {
David Srbecky09c2a6b2016-03-11 17:11:44 +000048 // Write .strtab and .symtab.
David Srbecky32210b92017-12-04 14:39:21 +000049 WriteDebugSymbols(builder, false /* mini-debug-info */, debug_info);
David Srbeckyc5bfa972016-02-05 15:49:10 +000050
David Srbecky09c2a6b2016-03-11 17:11:44 +000051 // Write .debug_frame.
David Srbecky32210b92017-12-04 14:39:21 +000052 WriteCFISection(builder, debug_info.compiled_methods, cfi_format, write_oat_patches);
David Srbecky09c2a6b2016-03-11 17:11:44 +000053
David Srbecky56da23c2017-09-08 19:59:15 +010054 // Group the methods into compilation units based on class.
55 std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit;
David Srbecky32210b92017-12-04 14:39:21 +000056 for (const MethodDebugInfo& mi : debug_info.compiled_methods) {
David Srbecky09c2a6b2016-03-11 17:11:44 +000057 if (mi.dex_file != nullptr) {
58 auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
David Srbecky56da23c2017-09-08 19:59:15 +010059 ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def];
David Srbecky09c2a6b2016-03-11 17:11:44 +000060 cu.methods.push_back(&mi);
61 // All methods must have the same addressing mode otherwise the min/max below does not work.
62 DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
63 cu.is_code_address_text_relative = mi.is_code_address_text_relative;
64 cu.code_address = std::min(cu.code_address, mi.code_address);
65 cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
David Srbeckyc5bfa972016-02-05 15:49:10 +000066 }
David Srbeckyc5bfa972016-02-05 15:49:10 +000067 }
68
David Srbecky56da23c2017-09-08 19:59:15 +010069 // Sort compilation units to make the compiler output deterministic.
70 std::vector<ElfCompilationUnit> compilation_units;
71 compilation_units.reserve(class_to_compilation_unit.size());
72 for (auto& it : class_to_compilation_unit) {
73 // The .debug_line section requires the methods to be sorted by code address.
74 std::stable_sort(it.second.methods.begin(),
75 it.second.methods.end(),
76 [](const MethodDebugInfo* a, const MethodDebugInfo* b) {
77 return a->code_address < b->code_address;
78 });
79 compilation_units.push_back(std::move(it.second));
80 }
81 std::sort(compilation_units.begin(),
82 compilation_units.end(),
83 [](ElfCompilationUnit& a, ElfCompilationUnit& b) {
84 // Sort by index of the first method within the method_infos array.
85 // This assumes that the order of method_infos is deterministic.
86 // Code address is not good for sorting due to possible duplicates.
87 return a.methods.front() < b.methods.front();
88 });
89
David Srbeckyc5bfa972016-02-05 15:49:10 +000090 // Write .debug_line section.
91 if (!compilation_units.empty()) {
92 ElfDebugLineWriter<ElfTypes> line_writer(builder);
93 line_writer.Start();
94 for (auto& compilation_unit : compilation_units) {
95 line_writer.WriteCompilationUnit(compilation_unit);
96 }
97 line_writer.End(write_oat_patches);
98 }
99
100 // Write .debug_info section.
101 if (!compilation_units.empty()) {
102 ElfDebugInfoWriter<ElfTypes> info_writer(builder);
103 info_writer.Start();
104 for (const auto& compilation_unit : compilation_units) {
105 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
106 cu_writer.Write(compilation_unit);
107 }
108 info_writer.End(write_oat_patches);
109 }
110}
111
David Srbecky154c57f2018-06-03 12:00:27 +0100112template <typename ElfTypes>
113static std::vector<uint8_t> MakeMiniDebugInfoInternal(
114 InstructionSet isa,
115 const InstructionSetFeatures* features,
116 typename ElfTypes::Addr text_section_address,
117 size_t text_section_size,
118 typename ElfTypes::Addr dex_section_address,
119 size_t dex_section_size,
120 const DebugInfo& debug_info) {
121 std::vector<uint8_t> buffer;
122 buffer.reserve(KB);
123 linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer);
124 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
125 new linker::ElfBuilder<ElfTypes>(isa, features, &out));
126 builder->Start(false /* write_program_headers */);
127 // Mirror ELF sections as NOBITS since the added symbols will reference them.
128 builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size);
129 if (dex_section_size != 0) {
130 builder->GetDex()->AllocateVirtualMemory(dex_section_address, dex_section_size);
131 }
132 WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info);
133 WriteCFISection(builder.get(),
134 debug_info.compiled_methods,
135 dwarf::DW_DEBUG_FRAME_FORMAT,
136 false /* write_oat_paches */);
137 builder->End();
138 CHECK(builder->Good());
139 std::vector<uint8_t> compressed_buffer;
140 compressed_buffer.reserve(buffer.size() / 4);
141 XzCompress(ArrayRef<uint8_t>(buffer), &compressed_buffer);
142 return compressed_buffer;
143}
144
David Srbeckyc5bfa972016-02-05 15:49:10 +0000145std::vector<uint8_t> MakeMiniDebugInfo(
146 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +0000147 const InstructionSetFeatures* features,
David Srbecky32210b92017-12-04 14:39:21 +0000148 uint64_t text_section_address,
149 size_t text_section_size,
150 uint64_t dex_section_address,
151 size_t dex_section_size,
152 const DebugInfo& debug_info) {
David Srbeckyc5bfa972016-02-05 15:49:10 +0000153 if (Is64BitInstructionSet(isa)) {
David Srbecky5d811202016-03-08 13:21:22 +0000154 return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
155 features,
David Srbecky32210b92017-12-04 14:39:21 +0000156 text_section_address,
157 text_section_size,
158 dex_section_address,
159 dex_section_size,
160 debug_info);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000161 } else {
David Srbecky5d811202016-03-08 13:21:22 +0000162 return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
163 features,
David Srbecky32210b92017-12-04 14:39:21 +0000164 text_section_address,
165 text_section_size,
166 dex_section_address,
167 dex_section_size,
168 debug_info);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000169 }
170}
171
David Srbeckybe50f9a2018-12-05 10:48:42 +0000172std::vector<uint8_t> MakeElfFileForJIT(
David Srbeckyfe736b72016-03-09 11:44:44 +0000173 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +0000174 const InstructionSetFeatures* features,
David Srbeckyf4886df2017-12-11 16:06:29 +0000175 bool mini_debug_info,
David Srbeckybe50f9a2018-12-05 10:48:42 +0000176 const MethodDebugInfo& method_info) {
177 using ElfTypes = ElfRuntimeTypes;
178 CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
179 CHECK_EQ(method_info.is_code_address_text_relative, false);
David Srbecky32210b92017-12-04 14:39:21 +0000180 DebugInfo debug_info{};
David Srbeckybe50f9a2018-12-05 10:48:42 +0000181 debug_info.compiled_methods = ArrayRef<const MethodDebugInfo>(&method_info, 1);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000182 std::vector<uint8_t> buffer;
183 buffer.reserve(KB);
Vladimir Marko74527972016-11-29 15:57:32 +0000184 linker::VectorOutputStream out("Debug ELF file", &buffer);
185 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
186 new linker::ElfBuilder<ElfTypes>(isa, features, &out));
David Srbeckyc5bfa972016-02-05 15:49:10 +0000187 // No program headers since the ELF file is not linked and has no allocated sections.
188 builder->Start(false /* write_program_headers */);
David Srbeckybe50f9a2018-12-05 10:48:42 +0000189 builder->GetText()->AllocateVirtualMemory(method_info.code_address, method_info.code_size);
David Srbeckyf4886df2017-12-11 16:06:29 +0000190 if (mini_debug_info) {
David Srbeckybe50f9a2018-12-05 10:48:42 +0000191 // The compression is great help for multiple methods but it is not worth it for a
192 // single method due to the overheads so skip the compression here for performance.
193 WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info);
194 WriteCFISection(builder.get(),
195 debug_info.compiled_methods,
196 dwarf::DW_DEBUG_FRAME_FORMAT,
197 false /* write_oat_paches */);
David Srbeckyf4886df2017-12-11 16:06:29 +0000198 } else {
David Srbeckyf4886df2017-12-11 16:06:29 +0000199 WriteDebugInfo(builder.get(),
David Srbecky32210b92017-12-04 14:39:21 +0000200 debug_info,
David Srbeckyf4886df2017-12-11 16:06:29 +0000201 dwarf::DW_DEBUG_FRAME_FORMAT,
202 false /* write_oat_patches */);
203 }
David Srbeckyc5bfa972016-02-05 15:49:10 +0000204 builder->End();
205 CHECK(builder->Good());
Vladimir Marko93205e32016-04-13 11:59:46 +0100206 return buffer;
David Srbeckyc5bfa972016-02-05 15:49:10 +0000207}
208
David Srbeckybe50f9a2018-12-05 10:48:42 +0000209std::vector<uint8_t> WriteDebugElfFileForClasses(
David Srbeckyfe736b72016-03-09 11:44:44 +0000210 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +0000211 const InstructionSetFeatures* features,
212 const ArrayRef<mirror::Class*>& types)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700213 REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckybe50f9a2018-12-05 10:48:42 +0000214 using ElfTypes = ElfRuntimeTypes;
215 CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
David Srbeckyc5bfa972016-02-05 15:49:10 +0000216 std::vector<uint8_t> buffer;
217 buffer.reserve(KB);
Vladimir Marko74527972016-11-29 15:57:32 +0000218 linker::VectorOutputStream out("Debug ELF file", &buffer);
219 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
220 new linker::ElfBuilder<ElfTypes>(isa, features, &out));
David Srbeckyc5bfa972016-02-05 15:49:10 +0000221 // No program headers since the ELF file is not linked and has no allocated sections.
222 builder->Start(false /* write_program_headers */);
223 ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
224 info_writer.Start();
225 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
226 cu_writer.Write(types);
227 info_writer.End(false /* write_oat_patches */);
228
229 builder->End();
230 CHECK(builder->Good());
Vladimir Marko93205e32016-04-13 11:59:46 +0100231 return buffer;
David Srbeckyc5bfa972016-02-05 15:49:10 +0000232}
233
David Srbeckyc5bfa972016-02-05 15:49:10 +0000234// Explicit instantiations
235template void WriteDebugInfo<ElfTypes32>(
Vladimir Marko74527972016-11-29 15:57:32 +0000236 linker::ElfBuilder<ElfTypes32>* builder,
David Srbecky32210b92017-12-04 14:39:21 +0000237 const DebugInfo& debug_info,
David Srbeckyc5bfa972016-02-05 15:49:10 +0000238 dwarf::CFIFormat cfi_format,
239 bool write_oat_patches);
240template void WriteDebugInfo<ElfTypes64>(
Vladimir Marko74527972016-11-29 15:57:32 +0000241 linker::ElfBuilder<ElfTypes64>* builder,
David Srbecky32210b92017-12-04 14:39:21 +0000242 const DebugInfo& debug_info,
David Srbeckyc5bfa972016-02-05 15:49:10 +0000243 dwarf::CFIFormat cfi_format,
244 bool write_oat_patches);
245
246} // namespace debug
247} // namespace art