blob: 6de45f55268e643129d7371c975097660036b4d9 [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();
36 this->PushUint32(0); // Length placeholder.
37 this->PushUint32(0); // CIE id.
38 this->PushUint8(1); // Version.
39 this->PushString("zR");
40 this->PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
41 this->PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor);
42 this->PushUleb128(return_address_register.num()); // ubyte in DWARF2.
43 this->PushUleb128(1); // z: Augmentation data size.
44 if (use_64bit_address_) {
45 this->PushUint8(0x04); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
46 } else {
47 this->PushUint8(0x03); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
48 }
49 this->PushData(initial_opcodes, initial_opcodes_size);
50 this->Pad(use_64bit_address_ ? 8 : 4);
51 this->UpdateUint32(cie_header_start_, this->data()->size() - cie_header_start_ - 4);
52 }
53
54 void WriteCIE(Reg return_address_register,
55 const DebugFrameOpCodeWriter<Allocator>& opcodes) {
56 WriteCIE(return_address_register, opcodes.data()->data(), opcodes.data()->size());
57 }
58
59 void WriteFDE(uint64_t initial_address,
60 uint64_t address_range,
61 const uint8_t* unwind_opcodes,
62 int unwind_opcodes_size) {
63 DCHECK(cie_header_start_ != ~0u);
64 size_t fde_header_start = this->data()->size();
65 this->PushUint32(0); // Length placeholder.
66 this->PushUint32(this->data()->size() - cie_header_start_); // 'CIE_pointer'
67 if (use_64bit_address_) {
68 this->PushUint64(initial_address);
69 this->PushUint64(address_range);
70 } else {
71 this->PushUint32(initial_address);
72 this->PushUint32(address_range);
73 }
74 this->PushUleb128(0); // Augmentation data size.
75 this->PushData(unwind_opcodes, unwind_opcodes_size);
76 this->Pad(use_64bit_address_ ? 8 : 4);
77 this->UpdateUint32(fde_header_start, this->data()->size() - fde_header_start - 4);
78 }
79
80 DebugFrameWriter(std::vector<uint8_t, Allocator>* buffer, bool use_64bit_address)
81 : Writer<Allocator>(buffer),
82 use_64bit_address_(use_64bit_address),
83 cie_header_start_(~0u) {
84 }
85
86 private:
87 bool use_64bit_address_;
88 size_t cie_header_start_;
89
90 DISALLOW_COPY_AND_ASSIGN(DebugFrameWriter);
91};
92
93} // namespace dwarf
94} // namespace art
95
96#endif // ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_