blob: b7e000aeb2d37a0c87527fd0e99a5ba799602558 [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
19#include <vector>
20
21#include "debug/dwarf/dwarf_constants.h"
22#include "debug/elf_compilation_unit.h"
23#include "debug/elf_debug_frame_writer.h"
24#include "debug/elf_debug_info_writer.h"
25#include "debug/elf_debug_line_writer.h"
26#include "debug/elf_debug_loc_writer.h"
27#include "debug/elf_gnu_debugdata_writer.h"
28#include "debug/elf_symtab_writer.h"
29#include "debug/method_debug_info.h"
30#include "elf_builder.h"
31#include "linker/vector_output_stream.h"
32#include "utils/array_ref.h"
33
34namespace art {
35namespace debug {
36
37template <typename ElfTypes>
38void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
39 const ArrayRef<const MethodDebugInfo>& method_infos,
40 dwarf::CFIFormat cfi_format,
41 bool write_oat_patches) {
David Srbecky09c2a6b2016-03-11 17:11:44 +000042 // Write .strtab and .symtab.
David Srbeckyc5bfa972016-02-05 15:49:10 +000043 WriteDebugSymbols(builder, method_infos, true /* with_signature */);
David Srbeckyc5bfa972016-02-05 15:49:10 +000044
David Srbecky09c2a6b2016-03-11 17:11:44 +000045 // Write .debug_frame.
46 WriteCFISection(builder, method_infos, cfi_format, write_oat_patches);
47
David Srbeckyc5bfa972016-02-05 15:49:10 +000048 // Group the methods into compilation units based on source file.
49 std::vector<ElfCompilationUnit> compilation_units;
50 const char* last_source_file = nullptr;
51 for (const MethodDebugInfo& mi : method_infos) {
David Srbecky09c2a6b2016-03-11 17:11:44 +000052 if (mi.dex_file != nullptr) {
53 auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
54 const char* source_file = mi.dex_file->GetSourceFile(dex_class_def);
55 if (compilation_units.empty() || source_file != last_source_file) {
56 compilation_units.push_back(ElfCompilationUnit());
57 }
58 ElfCompilationUnit& cu = compilation_units.back();
59 cu.methods.push_back(&mi);
60 // All methods must have the same addressing mode otherwise the min/max below does not work.
61 DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
62 cu.is_code_address_text_relative = mi.is_code_address_text_relative;
63 cu.code_address = std::min(cu.code_address, mi.code_address);
64 cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
65 last_source_file = source_file;
David Srbeckyc5bfa972016-02-05 15:49:10 +000066 }
David Srbeckyc5bfa972016-02-05 15:49:10 +000067 }
68
69 // Write .debug_line section.
70 if (!compilation_units.empty()) {
71 ElfDebugLineWriter<ElfTypes> line_writer(builder);
72 line_writer.Start();
73 for (auto& compilation_unit : compilation_units) {
74 line_writer.WriteCompilationUnit(compilation_unit);
75 }
76 line_writer.End(write_oat_patches);
77 }
78
79 // Write .debug_info section.
80 if (!compilation_units.empty()) {
81 ElfDebugInfoWriter<ElfTypes> info_writer(builder);
82 info_writer.Start();
83 for (const auto& compilation_unit : compilation_units) {
84 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
85 cu_writer.Write(compilation_unit);
86 }
87 info_writer.End(write_oat_patches);
88 }
89}
90
91std::vector<uint8_t> MakeMiniDebugInfo(
92 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +000093 const InstructionSetFeatures* features,
David Srbeckyc5bfa972016-02-05 15:49:10 +000094 size_t rodata_size,
95 size_t text_size,
96 const ArrayRef<const MethodDebugInfo>& method_infos) {
97 if (Is64BitInstructionSet(isa)) {
David Srbecky5d811202016-03-08 13:21:22 +000098 return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
99 features,
100 rodata_size,
101 text_size,
102 method_infos);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000103 } else {
David Srbecky5d811202016-03-08 13:21:22 +0000104 return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
105 features,
106 rodata_size,
107 text_size,
108 method_infos);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000109 }
110}
111
112template <typename ElfTypes>
Vladimir Marko93205e32016-04-13 11:59:46 +0100113static std::vector<uint8_t> WriteDebugElfFileForMethodsInternal(
David Srbeckyfe736b72016-03-09 11:44:44 +0000114 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +0000115 const InstructionSetFeatures* features,
David Srbeckyfe736b72016-03-09 11:44:44 +0000116 const ArrayRef<const MethodDebugInfo>& method_infos) {
David Srbeckyc5bfa972016-02-05 15:49:10 +0000117 std::vector<uint8_t> buffer;
118 buffer.reserve(KB);
119 VectorOutputStream out("Debug ELF file", &buffer);
David Srbecky5d811202016-03-08 13:21:22 +0000120 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
David Srbeckyc5bfa972016-02-05 15:49:10 +0000121 // No program headers since the ELF file is not linked and has no allocated sections.
122 builder->Start(false /* write_program_headers */);
123 WriteDebugInfo(builder.get(),
David Srbeckyfe736b72016-03-09 11:44:44 +0000124 method_infos,
David Srbeckyc5bfa972016-02-05 15:49:10 +0000125 dwarf::DW_DEBUG_FRAME_FORMAT,
126 false /* write_oat_patches */);
127 builder->End();
128 CHECK(builder->Good());
Vladimir Marko93205e32016-04-13 11:59:46 +0100129 return buffer;
David Srbeckyc5bfa972016-02-05 15:49:10 +0000130}
131
Vladimir Marko93205e32016-04-13 11:59:46 +0100132std::vector<uint8_t> WriteDebugElfFileForMethods(
David Srbeckyfe736b72016-03-09 11:44:44 +0000133 InstructionSet isa,
134 const InstructionSetFeatures* features,
135 const ArrayRef<const MethodDebugInfo>& method_infos) {
David Srbeckyc5bfa972016-02-05 15:49:10 +0000136 if (Is64BitInstructionSet(isa)) {
David Srbeckyfe736b72016-03-09 11:44:44 +0000137 return WriteDebugElfFileForMethodsInternal<ElfTypes64>(isa, features, method_infos);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000138 } else {
David Srbeckyfe736b72016-03-09 11:44:44 +0000139 return WriteDebugElfFileForMethodsInternal<ElfTypes32>(isa, features, method_infos);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000140 }
141}
142
143template <typename ElfTypes>
Vladimir Marko93205e32016-04-13 11:59:46 +0100144static std::vector<uint8_t> WriteDebugElfFileForClassesInternal(
David Srbeckyfe736b72016-03-09 11:44:44 +0000145 InstructionSet isa,
David Srbecky5d811202016-03-08 13:21:22 +0000146 const InstructionSetFeatures* features,
147 const ArrayRef<mirror::Class*>& types)
David Srbeckyc5bfa972016-02-05 15:49:10 +0000148 SHARED_REQUIRES(Locks::mutator_lock_) {
149 std::vector<uint8_t> buffer;
150 buffer.reserve(KB);
151 VectorOutputStream out("Debug ELF file", &buffer);
David Srbecky5d811202016-03-08 13:21:22 +0000152 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
David Srbeckyc5bfa972016-02-05 15:49:10 +0000153 // No program headers since the ELF file is not linked and has no allocated sections.
154 builder->Start(false /* write_program_headers */);
155 ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
156 info_writer.Start();
157 ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
158 cu_writer.Write(types);
159 info_writer.End(false /* write_oat_patches */);
160
161 builder->End();
162 CHECK(builder->Good());
Vladimir Marko93205e32016-04-13 11:59:46 +0100163 return buffer;
David Srbeckyc5bfa972016-02-05 15:49:10 +0000164}
165
Vladimir Marko93205e32016-04-13 11:59:46 +0100166std::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa,
167 const InstructionSetFeatures* features,
168 const ArrayRef<mirror::Class*>& types) {
David Srbeckyc5bfa972016-02-05 15:49:10 +0000169 if (Is64BitInstructionSet(isa)) {
David Srbecky5d811202016-03-08 13:21:22 +0000170 return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, features, types);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000171 } else {
David Srbecky5d811202016-03-08 13:21:22 +0000172 return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, features, types);
David Srbeckyc5bfa972016-02-05 15:49:10 +0000173 }
174}
175
David Srbecky09c2a6b2016-03-11 17:11:44 +0000176std::vector<MethodDebugInfo> MakeTrampolineInfos(const OatHeader& header) {
177 std::map<const char*, uint32_t> trampolines = {
178 { "interpreterToInterpreterBridge", header.GetInterpreterToInterpreterBridgeOffset() },
179 { "interpreterToCompiledCodeBridge", header.GetInterpreterToCompiledCodeBridgeOffset() },
180 { "jniDlsymLookup", header.GetJniDlsymLookupOffset() },
181 { "quickGenericJniTrampoline", header.GetQuickGenericJniTrampolineOffset() },
182 { "quickImtConflictTrampoline", header.GetQuickImtConflictTrampolineOffset() },
183 { "quickResolutionTrampoline", header.GetQuickResolutionTrampolineOffset() },
184 { "quickToInterpreterBridge", header.GetQuickToInterpreterBridgeOffset() },
185 };
186 std::vector<MethodDebugInfo> result;
187 for (const auto& it : trampolines) {
188 if (it.second != 0) {
189 MethodDebugInfo info = MethodDebugInfo();
190 info.trampoline_name = it.first;
191 info.isa = header.GetInstructionSet();
192 info.is_code_address_text_relative = true;
193 info.code_address = it.second - header.GetExecutableOffset();
194 info.code_size = 0; // The symbol lasts until the next symbol.
195 result.push_back(std::move(info));
196 }
197 }
198 return result;
199}
200
David Srbeckyc5bfa972016-02-05 15:49:10 +0000201// Explicit instantiations
202template void WriteDebugInfo<ElfTypes32>(
203 ElfBuilder<ElfTypes32>* builder,
204 const ArrayRef<const MethodDebugInfo>& method_infos,
205 dwarf::CFIFormat cfi_format,
206 bool write_oat_patches);
207template void WriteDebugInfo<ElfTypes64>(
208 ElfBuilder<ElfTypes64>* builder,
209 const ArrayRef<const MethodDebugInfo>& method_infos,
210 dwarf::CFIFormat cfi_format,
211 bool write_oat_patches);
212
213} // namespace debug
214} // namespace art