1b536247b1ce5de640eec81dddac47802cd074363David Srbecky/*
2b536247b1ce5de640eec81dddac47802cd074363David Srbecky * Copyright (C) 2015 The Android Open Source Project
3b536247b1ce5de640eec81dddac47802cd074363David Srbecky *
4b536247b1ce5de640eec81dddac47802cd074363David Srbecky * Licensed under the Apache License, Version 2.0 (the "License");
5b536247b1ce5de640eec81dddac47802cd074363David Srbecky * you may not use this file except in compliance with the License.
6b536247b1ce5de640eec81dddac47802cd074363David Srbecky * You may obtain a copy of the License at
7b536247b1ce5de640eec81dddac47802cd074363David Srbecky *
8b536247b1ce5de640eec81dddac47802cd074363David Srbecky *      http://www.apache.org/licenses/LICENSE-2.0
9b536247b1ce5de640eec81dddac47802cd074363David Srbecky *
10b536247b1ce5de640eec81dddac47802cd074363David Srbecky * Unless required by applicable law or agreed to in writing, software
11b536247b1ce5de640eec81dddac47802cd074363David Srbecky * distributed under the License is distributed on an "AS IS" BASIS,
12b536247b1ce5de640eec81dddac47802cd074363David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b536247b1ce5de640eec81dddac47802cd074363David Srbecky * See the License for the specific language governing permissions and
14b536247b1ce5de640eec81dddac47802cd074363David Srbecky * limitations under the License.
15b536247b1ce5de640eec81dddac47802cd074363David Srbecky */
16b536247b1ce5de640eec81dddac47802cd074363David Srbecky
174fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#ifndef ART_COMPILER_DEBUG_DWARF_HEADERS_H_
184fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#define ART_COMPILER_DEBUG_DWARF_HEADERS_H_
19b536247b1ce5de640eec81dddac47802cd074363David Srbecky
202f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky#include <cstdint>
212f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky
224fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/debug_frame_opcode_writer.h"
234fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/debug_info_entry_writer.h"
244fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/debug_line_opcode_writer.h"
254fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/dwarf_constants.h"
264fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/register.h"
274fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/writer.h"
2835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko#include "utils/array_ref.h"
29b536247b1ce5de640eec81dddac47802cd074363David Srbecky
30b536247b1ce5de640eec81dddac47802cd074363David Srbeckynamespace art {
31b536247b1ce5de640eec81dddac47802cd074363David Srbeckynamespace dwarf {
32b536247b1ce5de640eec81dddac47802cd074363David Srbecky
332f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky// Note that all headers start with 32-bit length.
342f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky// DWARF also supports 64-bit lengths, but we never use that.
352f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky// It is intended to support very large debug sections (>4GB),
362f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky// and compilers are expected *not* to use it by default.
372f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky// In particular, it is not related to machine architecture.
382f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky
39ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// Write common information entry (CIE) to .debug_frame or .eh_frame section.
40ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Markotemplate<typename Vector>
416d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbeckyvoid WriteCIE(bool is64bit,
426d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              Reg return_address_register,
436d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              const DebugFrameOpCodeWriter<Vector>& opcodes,
446d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              CFIFormat format,
456d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              std::vector<uint8_t>* buffer) {
46ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
47ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko
486d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  Writer<> writer(buffer);
49b536247b1ce5de640eec81dddac47802cd074363David Srbecky  size_t cie_header_start_ = writer.data()->size();
502f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  writer.PushUint32(0);  // Length placeholder.
51ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky  writer.PushUint32((format == DW_EH_FRAME_FORMAT) ? 0 : 0xFFFFFFFF);  // CIE id.
52b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint8(1);   // Version.
53b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushString("zR");
54ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushUleb128(DebugFrameOpCodeWriter<Vector>::kCodeAlignmentFactor);
55ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushSleb128(DebugFrameOpCodeWriter<Vector>::kDataAlignmentFactor);
56b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUleb128(return_address_register.num());  // ubyte in DWARF2.
57b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUleb128(1);  // z: Augmentation data size.
58b536247b1ce5de640eec81dddac47802cd074363David Srbecky  if (is64bit) {
596d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    if (format == DW_EH_FRAME_FORMAT) {
6017065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky      writer.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata8);   // R: Pointer encoding.
6117065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky    } else {
626d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      DCHECK(format == DW_DEBUG_FRAME_FORMAT);
6317065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky      writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata8);  // R: Pointer encoding.
6417065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky    }
65b536247b1ce5de640eec81dddac47802cd074363David Srbecky  } else {
666d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    if (format == DW_EH_FRAME_FORMAT) {
6717065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky      writer.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);   // R: Pointer encoding.
6817065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky    } else {
696d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      DCHECK(format == DW_DEBUG_FRAME_FORMAT);
7017065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky      writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata4);  // R: Pointer encoding.
7117065880693d1b15ffeb60b9955a2d092839977fDavid Srbecky    }
72b536247b1ce5de640eec81dddac47802cd074363David Srbecky  }
7391cb54e6caf8b06546c416e7f7467f1c03b3a757David Srbecky  writer.PushData(opcodes.data());
74b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.Pad(is64bit ? 8 : 4);
752f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4);
76b536247b1ce5de640eec81dddac47802cd074363David Srbecky}
77b536247b1ce5de640eec81dddac47802cd074363David Srbecky
78ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// Write frame description entry (FDE) to .debug_frame or .eh_frame section.
7935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Markoinline
806d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbeckyvoid WriteFDE(bool is64bit,
816d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              uint64_t section_address,  // Absolute address of the section.
826d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              uint64_t cie_address,  // Absolute address of last CIE.
836d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              uint64_t code_address,
846d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              uint64_t code_size,
856d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              const ArrayRef<const uint8_t>& opcodes,
866d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              CFIFormat format,
876d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              uint64_t buffer_address,  // Address of buffer in linked application.
886d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              std::vector<uint8_t>* buffer,
896d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky              std::vector<uintptr_t>* patch_locations) {
906d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  CHECK_GE(cie_address, section_address);
916d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  CHECK_GE(buffer_address, section_address);
926d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
936d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  Writer<> writer(buffer);
94b536247b1ce5de640eec81dddac47802cd074363David Srbecky  size_t fde_header_start = writer.data()->size();
952f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  writer.PushUint32(0);  // Length placeholder.
96ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky  if (format == DW_EH_FRAME_FORMAT) {
976d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    uint32_t cie_pointer = (buffer_address + buffer->size()) - cie_address;
98ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky    writer.PushUint32(cie_pointer);
99ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky  } else {
1006d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    DCHECK(format == DW_DEBUG_FRAME_FORMAT);
1016d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    uint32_t cie_pointer = cie_address - section_address;
102ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky    writer.PushUint32(cie_pointer);
103ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky  }
1046d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (format == DW_EH_FRAME_FORMAT) {
1056d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    // .eh_frame encodes the location as relative address.
1066d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    code_address -= buffer_address + buffer->size();
1076d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  } else {
1086d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    DCHECK(format == DW_DEBUG_FRAME_FORMAT);
1096d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    // Relocate code_address if it has absolute value.
1106d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    patch_locations->push_back(buffer_address + buffer->size() - section_address);
1116d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  }
112b536247b1ce5de640eec81dddac47802cd074363David Srbecky  if (is64bit) {
1136d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    writer.PushUint64(code_address);
1146d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    writer.PushUint64(code_size);
115b536247b1ce5de640eec81dddac47802cd074363David Srbecky  } else {
1166d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    writer.PushUint32(code_address);
1176d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    writer.PushUint32(code_size);
118b536247b1ce5de640eec81dddac47802cd074363David Srbecky  }
119b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUleb128(0);  // Augmentation data size.
12091cb54e6caf8b06546c416e7f7467f1c03b3a757David Srbecky  writer.PushData(opcodes.data(), opcodes.size());
121b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.Pad(is64bit ? 8 : 4);
1222f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  writer.UpdateUint32(fde_header_start, writer.data()->size() - fde_header_start - 4);
123b536247b1ce5de640eec81dddac47802cd074363David Srbecky}
124b536247b1ce5de640eec81dddac47802cd074363David Srbecky
125b536247b1ce5de640eec81dddac47802cd074363David Srbecky// Write compilation unit (CU) to .debug_info section.
126ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Markotemplate<typename Vector>
127b536247b1ce5de640eec81dddac47802cd074363David Srbeckyvoid WriteDebugInfoCU(uint32_t debug_abbrev_offset,
128ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko                      const DebugInfoEntryWriter<Vector>& entries,
129b851b49eee0a77720347a4f777c07d4531302655David Srbecky                      size_t debug_info_offset,  // offset from start of .debug_info.
1302f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky                      std::vector<uint8_t>* debug_info,
1312f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky                      std::vector<uintptr_t>* debug_info_patches) {
132ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
133ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko
134b536247b1ce5de640eec81dddac47802cd074363David Srbecky  Writer<> writer(debug_info);
135b536247b1ce5de640eec81dddac47802cd074363David Srbecky  size_t start = writer.data()->size();
136b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint32(0);  // Length placeholder.
1370fd295f8663e658de429f85f241a142169477335David Srbecky  writer.PushUint16(4);  // Version.
138b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint32(debug_abbrev_offset);
1392f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  writer.PushUint8(entries.Is64bit() ? 8 : 4);
1402f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  size_t entries_offset = writer.data()->size();
14104b0526d60de4e9979fc486d2ba655247d211d0bDavid Srbecky  DCHECK_EQ(entries_offset, DebugInfoEntryWriter<Vector>::kCompilationUnitHeaderSize);
14291cb54e6caf8b06546c416e7f7467f1c03b3a757David Srbecky  writer.PushData(entries.data());
143b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.UpdateUint32(start, writer.data()->size() - start - 4);
1442f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  // Copy patch locations and make them relative to .debug_info section.
1452f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  for (uintptr_t patch_location : entries.GetPatchLocations()) {
146b851b49eee0a77720347a4f777c07d4531302655David Srbecky    debug_info_patches->push_back(debug_info_offset + entries_offset + patch_location);
1472f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  }
148b536247b1ce5de640eec81dddac47802cd074363David Srbecky}
149b536247b1ce5de640eec81dddac47802cd074363David Srbecky
150b536247b1ce5de640eec81dddac47802cd074363David Srbeckystruct FileEntry {
151b536247b1ce5de640eec81dddac47802cd074363David Srbecky  std::string file_name;
152b536247b1ce5de640eec81dddac47802cd074363David Srbecky  int directory_index;
153b536247b1ce5de640eec81dddac47802cd074363David Srbecky  int modification_time;
154b536247b1ce5de640eec81dddac47802cd074363David Srbecky  int file_size;
155b536247b1ce5de640eec81dddac47802cd074363David Srbecky};
156b536247b1ce5de640eec81dddac47802cd074363David Srbecky
157b536247b1ce5de640eec81dddac47802cd074363David Srbecky// Write line table to .debug_line section.
158ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Markotemplate<typename Vector>
159b536247b1ce5de640eec81dddac47802cd074363David Srbeckyvoid WriteDebugLineTable(const std::vector<std::string>& include_directories,
160b536247b1ce5de640eec81dddac47802cd074363David Srbecky                         const std::vector<FileEntry>& files,
161ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko                         const DebugLineOpCodeWriter<Vector>& opcodes,
162b851b49eee0a77720347a4f777c07d4531302655David Srbecky                         size_t debug_line_offset,  // offset from start of .debug_line.
1632f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky                         std::vector<uint8_t>* debug_line,
1642f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky                         std::vector<uintptr_t>* debug_line_patches) {
165ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
166ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko
167b536247b1ce5de640eec81dddac47802cd074363David Srbecky  Writer<> writer(debug_line);
168b536247b1ce5de640eec81dddac47802cd074363David Srbecky  size_t header_start = writer.data()->size();
169b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint32(0);  // Section-length placeholder.
1700fd295f8663e658de429f85f241a142169477335David Srbecky  writer.PushUint16(3);  // .debug_line version.
171b536247b1ce5de640eec81dddac47802cd074363David Srbecky  size_t header_length_pos = writer.data()->size();
172b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint32(0);  // Header-length placeholder.
173b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint8(1 << opcodes.GetCodeFactorBits());
174ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kDefaultIsStmt ? 1 : 0);
175ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushInt8(DebugLineOpCodeWriter<Vector>::kLineBase);
176ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kLineRange);
177ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kOpcodeBase);
178ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  static const int opcode_lengths[DebugLineOpCodeWriter<Vector>::kOpcodeBase] = {
179b536247b1ce5de640eec81dddac47802cd074363David Srbecky      0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 };
180ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko  for (int i = 1; i < DebugLineOpCodeWriter<Vector>::kOpcodeBase; i++) {
181b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushUint8(opcode_lengths[i]);
182b536247b1ce5de640eec81dddac47802cd074363David Srbecky  }
183b536247b1ce5de640eec81dddac47802cd074363David Srbecky  for (const std::string& directory : include_directories) {
184b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushData(directory.data(), directory.size() + 1);
185b536247b1ce5de640eec81dddac47802cd074363David Srbecky  }
186b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint8(0);  // Terminate include_directories list.
187b536247b1ce5de640eec81dddac47802cd074363David Srbecky  for (const FileEntry& file : files) {
188b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushData(file.file_name.data(), file.file_name.size() + 1);
189b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushUleb128(file.directory_index);
190b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushUleb128(file.modification_time);
191b536247b1ce5de640eec81dddac47802cd074363David Srbecky    writer.PushUleb128(file.file_size);
192b536247b1ce5de640eec81dddac47802cd074363David Srbecky  }
193b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.PushUint8(0);  // Terminate file list.
194b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.UpdateUint32(header_length_pos, writer.data()->size() - header_length_pos - 4);
1952f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  size_t opcodes_offset = writer.data()->size();
19691cb54e6caf8b06546c416e7f7467f1c03b3a757David Srbecky  writer.PushData(opcodes.data());
197b536247b1ce5de640eec81dddac47802cd074363David Srbecky  writer.UpdateUint32(header_start, writer.data()->size() - header_start - 4);
1982f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  // Copy patch locations and make them relative to .debug_line section.
1992f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  for (uintptr_t patch_location : opcodes.GetPatchLocations()) {
200b851b49eee0a77720347a4f777c07d4531302655David Srbecky    debug_line_patches->push_back(debug_line_offset + opcodes_offset + patch_location);
2012f6cdb01f74772c1c521a125776ef57ea3c73d43David Srbecky  }
202b536247b1ce5de640eec81dddac47802cd074363David Srbecky}
203b536247b1ce5de640eec81dddac47802cd074363David Srbecky
204b536247b1ce5de640eec81dddac47802cd074363David Srbecky}  // namespace dwarf
205b536247b1ce5de640eec81dddac47802cd074363David Srbecky}  // namespace art
206b536247b1ce5de640eec81dddac47802cd074363David Srbecky
2074fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#endif  // ART_COMPILER_DEBUG_DWARF_HEADERS_H_
208