1 /*
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_WRITER_H_
18 #define ART_COMPILER_DWARF_WRITER_H_
19 
20 #include <vector>
21 #include "base/bit_utils.h"
22 #include "base/logging.h"
23 #include "leb128.h"
24 
25 namespace art {
26 namespace dwarf {
27 
28 // The base class for all DWARF writers.
29 template<typename Allocator = std::allocator<uint8_t>>
30 class Writer {
31  public:
PushUint8(int value)32   void PushUint8(int value) {
33     DCHECK_GE(value, 0);
34     DCHECK_LE(value, UINT8_MAX);
35     data_->push_back(value & 0xff);
36   }
37 
PushUint16(int value)38   void PushUint16(int value) {
39     DCHECK_GE(value, 0);
40     DCHECK_LE(value, UINT16_MAX);
41     data_->push_back((value >> 0) & 0xff);
42     data_->push_back((value >> 8) & 0xff);
43   }
44 
PushUint32(uint32_t value)45   void PushUint32(uint32_t value) {
46     data_->push_back((value >> 0) & 0xff);
47     data_->push_back((value >> 8) & 0xff);
48     data_->push_back((value >> 16) & 0xff);
49     data_->push_back((value >> 24) & 0xff);
50   }
51 
PushUint32(int value)52   void PushUint32(int value) {
53     DCHECK_GE(value, 0);
54     PushUint32(static_cast<uint32_t>(value));
55   }
56 
PushUint32(uint64_t value)57   void PushUint32(uint64_t value) {
58     DCHECK_LE(value, UINT32_MAX);
59     PushUint32(static_cast<uint32_t>(value));
60   }
61 
PushUint64(uint64_t value)62   void PushUint64(uint64_t value) {
63     data_->push_back((value >> 0) & 0xff);
64     data_->push_back((value >> 8) & 0xff);
65     data_->push_back((value >> 16) & 0xff);
66     data_->push_back((value >> 24) & 0xff);
67     data_->push_back((value >> 32) & 0xff);
68     data_->push_back((value >> 40) & 0xff);
69     data_->push_back((value >> 48) & 0xff);
70     data_->push_back((value >> 56) & 0xff);
71   }
72 
PushInt8(int value)73   void PushInt8(int value) {
74     DCHECK_GE(value, INT8_MIN);
75     DCHECK_LE(value, INT8_MAX);
76     PushUint8(static_cast<uint8_t>(value));
77   }
78 
PushInt16(int value)79   void PushInt16(int value) {
80     DCHECK_GE(value, INT16_MIN);
81     DCHECK_LE(value, INT16_MAX);
82     PushUint16(static_cast<uint16_t>(value));
83   }
84 
PushInt32(int value)85   void PushInt32(int value) {
86     PushUint32(static_cast<uint32_t>(value));
87   }
88 
PushInt64(int64_t value)89   void PushInt64(int64_t value) {
90     PushUint64(static_cast<uint64_t>(value));
91   }
92 
93   // Variable-length encoders.
94 
PushUleb128(uint32_t value)95   void PushUleb128(uint32_t value) {
96     EncodeUnsignedLeb128(data_, value);
97   }
98 
PushUleb128(int value)99   void PushUleb128(int value) {
100     DCHECK_GE(value, 0);
101     EncodeUnsignedLeb128(data_, value);
102   }
103 
PushSleb128(int value)104   void PushSleb128(int value) {
105     EncodeSignedLeb128(data_, value);
106   }
107 
108   // Miscellaneous functions.
109 
PushString(const char * value)110   void PushString(const char* value) {
111     data_->insert(data_->end(), value, value + strlen(value) + 1);
112   }
113 
PushData(const void * ptr,size_t size)114   void PushData(const void* ptr, size_t size) {
115     const char* p = reinterpret_cast<const char*>(ptr);
116     data_->insert(data_->end(), p, p + size);
117   }
118 
119   template<typename Allocator2>
PushData(const std::vector<uint8_t,Allocator2> * buffer)120   void PushData(const std::vector<uint8_t, Allocator2>* buffer) {
121     data_->insert(data_->end(), buffer->begin(), buffer->end());
122   }
123 
UpdateUint32(size_t offset,uint32_t value)124   void UpdateUint32(size_t offset, uint32_t value) {
125     DCHECK_LT(offset + 3, data_->size());
126     (*data_)[offset + 0] = (value >> 0) & 0xFF;
127     (*data_)[offset + 1] = (value >> 8) & 0xFF;
128     (*data_)[offset + 2] = (value >> 16) & 0xFF;
129     (*data_)[offset + 3] = (value >> 24) & 0xFF;
130   }
131 
UpdateUint64(size_t offset,uint64_t value)132   void UpdateUint64(size_t offset, uint64_t value) {
133     DCHECK_LT(offset + 7, data_->size());
134     (*data_)[offset + 0] = (value >> 0) & 0xFF;
135     (*data_)[offset + 1] = (value >> 8) & 0xFF;
136     (*data_)[offset + 2] = (value >> 16) & 0xFF;
137     (*data_)[offset + 3] = (value >> 24) & 0xFF;
138     (*data_)[offset + 4] = (value >> 32) & 0xFF;
139     (*data_)[offset + 5] = (value >> 40) & 0xFF;
140     (*data_)[offset + 6] = (value >> 48) & 0xFF;
141     (*data_)[offset + 7] = (value >> 56) & 0xFF;
142   }
143 
UpdateUleb128(size_t offset,uint32_t value)144   void UpdateUleb128(size_t offset, uint32_t value) {
145     DCHECK_LE(offset + UnsignedLeb128Size(value), data_->size());
146     UpdateUnsignedLeb128(data_->data() + offset, value);
147   }
148 
Pop()149   void Pop() {
150     return data_->pop_back();
151   }
152 
Pad(int alignment)153   void Pad(int alignment) {
154     DCHECK_NE(alignment, 0);
155     data_->resize(RoundUp(data_->size(), alignment), 0);
156   }
157 
data()158   const std::vector<uint8_t, Allocator>* data() const {
159     return data_;
160   }
161 
Writer(std::vector<uint8_t,Allocator> * buffer)162   explicit Writer(std::vector<uint8_t, Allocator>* buffer) : data_(buffer) { }
163 
164  private:
165   std::vector<uint8_t, Allocator>* data_;
166 
167   DISALLOW_COPY_AND_ASSIGN(Writer);
168 };
169 
170 }  // namespace dwarf
171 }  // namespace art
172 
173 #endif  // ART_COMPILER_DWARF_WRITER_H_
174