blob: b104cc940897ee0b44469c4a684c926e9c909973 [file] [log] [blame]
David Srbecky15c19752015-03-31 14:53:55 +00001/*
2 * Copyright (C) 2015 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#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
18#define ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
19
20#include "debug_frame_opcode_writer.h"
21#include "dwarf.h"
22#include "writer.h"
23
24namespace art {
25namespace dwarf {
26
27// Writer for the .eh_frame section (which extends .debug_frame specification).
28template<typename Allocator = std::allocator<uint8_t>>
29class DebugFrameWriter FINAL : private Writer<Allocator> {
30 public:
31 void WriteCIE(Reg return_address_register,
32 const uint8_t* initial_opcodes,
33 int initial_opcodes_size) {
34 DCHECK(cie_header_start_ == ~0u);
35 cie_header_start_ = this->data()->size();
David Srbecky1109fb32015-04-07 20:21:06 +010036 if (use_64bit_address_) {
37 // TODO: This is not related to being 64bit.
38 this->PushUint32(0xffffffff);
39 this->PushUint64(0); // Length placeholder.
40 this->PushUint64(0); // CIE id.
41 } else {
42 this->PushUint32(0); // Length placeholder.
43 this->PushUint32(0); // CIE id.
44 }
David Srbecky15c19752015-03-31 14:53:55 +000045 this->PushUint8(1); // Version.
46 this->PushString("zR");
47 this->PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
48 this->PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor);
49 this->PushUleb128(return_address_register.num()); // ubyte in DWARF2.
50 this->PushUleb128(1); // z: Augmentation data size.
51 if (use_64bit_address_) {
52 this->PushUint8(0x04); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
53 } else {
54 this->PushUint8(0x03); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
55 }
56 this->PushData(initial_opcodes, initial_opcodes_size);
57 this->Pad(use_64bit_address_ ? 8 : 4);
David Srbecky1109fb32015-04-07 20:21:06 +010058 if (use_64bit_address_) {
59 this->UpdateUint64(cie_header_start_ + 4, this->data()->size() - cie_header_start_ - 12);
60 } else {
61 this->UpdateUint32(cie_header_start_, this->data()->size() - cie_header_start_ - 4);
62 }
David Srbecky15c19752015-03-31 14:53:55 +000063 }
64
65 void WriteCIE(Reg return_address_register,
66 const DebugFrameOpCodeWriter<Allocator>& opcodes) {
67 WriteCIE(return_address_register, opcodes.data()->data(), opcodes.data()->size());
68 }
69
70 void WriteFDE(uint64_t initial_address,
71 uint64_t address_range,
72 const uint8_t* unwind_opcodes,
73 int unwind_opcodes_size) {
74 DCHECK(cie_header_start_ != ~0u);
75 size_t fde_header_start = this->data()->size();
David Srbecky1109fb32015-04-07 20:21:06 +010076 if (use_64bit_address_) {
77 // TODO: This is not related to being 64bit.
78 this->PushUint32(0xffffffff);
79 this->PushUint64(0); // Length placeholder.
80 this->PushUint64(this->data()->size() - cie_header_start_); // 'CIE_pointer'
81 } else {
82 this->PushUint32(0); // Length placeholder.
83 this->PushUint32(this->data()->size() - cie_header_start_); // 'CIE_pointer'
84 }
David Srbecky15c19752015-03-31 14:53:55 +000085 if (use_64bit_address_) {
86 this->PushUint64(initial_address);
87 this->PushUint64(address_range);
88 } else {
89 this->PushUint32(initial_address);
90 this->PushUint32(address_range);
91 }
92 this->PushUleb128(0); // Augmentation data size.
93 this->PushData(unwind_opcodes, unwind_opcodes_size);
94 this->Pad(use_64bit_address_ ? 8 : 4);
David Srbecky1109fb32015-04-07 20:21:06 +010095 if (use_64bit_address_) {
96 this->UpdateUint64(fde_header_start + 4, this->data()->size() - fde_header_start - 12);
97 } else {
98 this->UpdateUint32(fde_header_start, this->data()->size() - fde_header_start - 4);
99 }
David Srbecky15c19752015-03-31 14:53:55 +0000100 }
101
102 DebugFrameWriter(std::vector<uint8_t, Allocator>* buffer, bool use_64bit_address)
103 : Writer<Allocator>(buffer),
104 use_64bit_address_(use_64bit_address),
105 cie_header_start_(~0u) {
106 }
107
108 private:
109 bool use_64bit_address_;
110 size_t cie_header_start_;
111
112 DISALLOW_COPY_AND_ASSIGN(DebugFrameWriter);
113};
114
115} // namespace dwarf
116} // namespace art
117
118#endif // ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_