elf_writer_quick.cc revision 131980fc9aeb2b4d03480443e0fb494c76ce03a2
16a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom/*
26a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Copyright (C) 2012 The Android Open Source Project
36a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
46a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
56a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * you may not use this file except in compliance with the License.
66a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * You may obtain a copy of the License at
76a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
86a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
96a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * See the License for the specific language governing permissions and
146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * limitations under the License.
156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom */
166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "elf_writer_quick.h"
186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
19e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include <unordered_map>
20626a1666015b0fa201e979870baf06afa93b65e7David Srbecky#include <unordered_set>
21e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
22f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky#include "base/casts.h"
236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/logging.h"
2410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "base/stl_util.h"
2520f85597828194c12be10d3a927999def066555eVladimir Marko#include "compiled_method.h"
2620f85597828194c12be10d3a927999def066555eVladimir Marko#include "driver/compiler_options.h"
2710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "dwarf/method_debug_info.h"
2810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "elf.h"
2954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "elf_builder.h"
3050cfe74daaece80853cb3b45d4338329b7d0345bNicolas Geoffray#include "elf_utils.h"
313b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "elf_writer_debug.h"
326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h"
3379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe#include "leb128.h"
34131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/buffered_output_stream.h"
35131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/file_output_stream.h"
366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "utils.h"
376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art {
396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
40ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// .eh_frame and .debug_frame are almost identical.
41ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// Except for some minor formatting differences, the main difference
42ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// is that .eh_frame is allocated within the running program because
43ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// it is used by C++ exception handling (which we do not use so we
44ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// can choose either).  C++ compilers generally tend to use .eh_frame
45ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// because if they need it sometimes, they might as well always use it.
46aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbecky// Let's use .debug_frame because it is easier to strip or compress.
47aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbeckyconstexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
48ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky
49388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// The ARM specification defines three special mapping symbols
50388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// $a, $t and $d which mark ARM, Thumb and data ranges respectively.
51388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// These symbols can be used by tools, for example, to pretty
52388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// print instructions correctly.  Objdump will use them if they
53388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// exist, but it will still work well without them.
54388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// However, these extra symbols take space, so let's just generate
55388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// one symbol which marks the whole .text section as code.
56388d2861ce185fe9bbf1989f1467031467bd1de7David Srbeckyconstexpr bool kGenerateSingleArmMappingSymbol = true;
57388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky
58533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
5910c13565474de2786aad7c2e79757ea250747a15Vladimir Markoclass ElfWriterQuick FINAL : public ElfWriter {
6010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko public:
6110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  ElfWriterQuick(InstructionSet instruction_set,
6210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                 const CompilerOptions* compiler_options,
6310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                 File* elf_file);
6410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  ~ElfWriterQuick();
6510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
6610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void Start() OVERRIDE;
6710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  OutputStream* StartRoData() OVERRIDE;
6810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void EndRoData(OutputStream* rodata) OVERRIDE;
6910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  OutputStream* StartText() OVERRIDE;
7010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void EndText(OutputStream* text) OVERRIDE;
7110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void SetBssSize(size_t bss_size) OVERRIDE;
7210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void WriteDynamicSection() OVERRIDE;
7310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE;
7410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE;
7510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  bool End() OVERRIDE;
7610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
77131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko  virtual OutputStream* GetStream() OVERRIDE;
78131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko
7910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
8010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                               std::vector<uint8_t>* buffer);
8110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
8210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko private:
8310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  const CompilerOptions* const compiler_options_;
8410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  File* const elf_file_;
8510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  std::unique_ptr<BufferedOutputStream> output_stream_;
8610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
8710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
8810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
8910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko};
9010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
9110c13565474de2786aad7c2e79757ea250747a15Vladimir Markostd::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
9210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                                                const CompilerOptions* compiler_options,
9310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                                                File* elf_file) {
9410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  if (Is64BitInstructionSet(instruction_set)) {
9510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file);
9610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  } else {
9710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file);
9810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  }
99b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
100b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
101533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
10210c13565474de2786aad7c2e79757ea250747a15Vladimir Markostatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
10310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                              const ArrayRef<const dwarf::MethodDebugInfo>& method_infos);
10410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
10510c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
10610c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
10710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                                         const CompilerOptions* compiler_options,
10810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                                         File* elf_file)
10910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    : ElfWriter(),
11010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      compiler_options_(compiler_options),
11110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      elf_file_(elf_file),
11210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))),
11310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {}
11454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
115533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
11610c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
117bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
11810c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
11910c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::Start() {
12010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  builder_->Start();
12110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
12210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
12310c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
12410c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
12510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  auto* rodata = builder_->GetRoData();
1266d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  rodata->Start();
12710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  return rodata;
12810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
129bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
13010c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
13110c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
13210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  CHECK_EQ(builder_->GetRoData(), rodata);
13310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  builder_->GetRoData()->End();
13410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
13510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
13610c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
13710c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::StartText() {
13810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  auto* text = builder_->GetText();
1396d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  text->Start();
14010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  return text;
14110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
14210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko
14310c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
14410c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
14510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  CHECK_EQ(builder_->GetText(), text);
14610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  builder_->GetText()->End();
14710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
148033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky
14910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
15010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) {
15110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  auto* bss = builder_->GetBss();
15210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  if (bss_size != 0u) {
1536d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bss->Start();
15410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    bss->SetSize(bss_size);
1556d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bss->End();
1566d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  }
15710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
158bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
15910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
16010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
16110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  builder_->WriteDynamicSection(elf_file_->GetPath());
16210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
163bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
16410c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
16510c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WriteDebugInfo(
16610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
16710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  if (compiler_options_->GetGenerateDebugInfo()) {
1686d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    if (!method_infos.empty()) {
169bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky      // Add methods to .symtab.
17010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      WriteDebugSymbols(builder_.get(), method_infos);
1716d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      // Generate CFI (stack unwinding information).
17210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      dwarf::WriteCFISection(builder_.get(), method_infos, kCFIFormat);
1736d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      // Write DWARF .debug_* sections.
17410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      dwarf::WriteDebugSections(builder_.get(), method_infos);
175bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky    }
1766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
17710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
1786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
17910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
18010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WritePatchLocations(
18110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    const ArrayRef<const uintptr_t>& patch_locations) {
182f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky  // Add relocation section for .text.
18310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  if (compiler_options_->GetIncludePatchInformation()) {
184f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky    // Note that ElfWriter::Fixup will be called regardless and therefore
185f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky    // we need to include oat_patches for debug sections unconditionally.
18610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    builder_->WritePatches(".text.oat_patches", patch_locations);
18753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
18810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}
18953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
19010c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes>
19110c13565474de2786aad7c2e79757ea250747a15Vladimir Markobool ElfWriterQuick<ElfTypes>::End() {
19210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  builder_->End();
1936d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
19410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  return builder_->Good();
195b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
196ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
197533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
198131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::GetStream() {
199131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko  return builder_->GetStream();
200131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko}
201131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko
202131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Markotemplate <typename ElfTypes>
20310c13565474de2786aad7c2e79757ea250747a15Vladimir Markostatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
20410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                              const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
205388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky  bool generated_mapping_symbol = false;
2066d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* strtab = builder->GetStrTab();
2076d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* symtab = builder->GetSymTab();
2086d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
20910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  if (method_infos.empty()) {
2106d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    return;
2116d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  }
212626a1666015b0fa201e979870baf06afa93b65e7David Srbecky
213626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  // Find all addresses (low_pc) which contain deduped methods.
214626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  // The first instance of method is not marked deduped_, but the rest is.
215626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  std::unordered_set<uint32_t> deduped_addresses;
21610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  for (const dwarf::MethodDebugInfo& info : method_infos) {
21710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    if (info.deduped_) {
21810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko      deduped_addresses.insert(info.low_pc_);
219626a1666015b0fa201e979870baf06afa93b65e7David Srbecky    }
220626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  }
221626a1666015b0fa201e979870baf06afa93b65e7David Srbecky
2226d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->Start();
2236d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->Write("");  // strtab should start with empty string.
22410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko  for (const dwarf::MethodDebugInfo& info : method_infos) {
22510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    if (info.deduped_) {
2266d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky      continue;  // Add symbol only for the first instance.
2276d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky    }
22810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true);
22910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) {
230626a1666015b0fa201e979870baf06afa93b65e7David Srbecky      name += " [DEDUPED]";
2310df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky    }
2320df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky
23310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    uint32_t low_pc = info.low_pc_;
2346f7158927fee233255f8e96719c374694b10cad3David Srbecky    // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
23510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    low_pc += info.compiled_method_->CodeDelta();
2366d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    symtab->Add(strtab->Write(name), builder->GetText(), low_pc,
23710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko                true, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC);
23854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
239f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
240f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    // instructions, so that disassembler tools can correctly disassemble.
241388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky    // Note that even if we generate just a single mapping symbol, ARM's Streamline
242388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky    // requires it to match function symbol.  Just address 0 does not work.
24310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko    if (info.compiled_method_->GetInstructionSet() == kThumb2) {
244388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky      if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
24510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko        symtab->Add(strtab->Write("$t"), builder->GetText(), info.low_pc_ & ~1,
2466d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky                    true, 0, STB_LOCAL, STT_NOTYPE);
247388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky        generated_mapping_symbol = true;
248388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky      }
249f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    }
25054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
2516d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->End();
2526d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
2536d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  // Symbols are buffered and written after names (because they are smaller).
2546d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  // We could also do two passes in this function to avoid the buffering.
2556d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->Start();
2566d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->Write();
2576d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->End();
25854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe}
25954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
260f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray// Explicit instantiations
261533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes32>;
262533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes64>;
263f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray
2646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}  // namespace art
265