]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Symbol / ArmUnwindInfo.cpp
1 //===-- ArmUnwindInfo.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include <vector>
11
12 #include "Utility/ARM_DWARF_Registers.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/Section.h"
15 #include "lldb/Symbol/ArmUnwindInfo.h"
16 #include "lldb/Symbol/SymbolVendor.h"
17 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Utility/Endian.h"
19
20 /*
21  * Unwind information reader and parser for the ARM exception handling ABI
22  *
23  * Implemented based on:
24  *     Exception Handling ABI for the ARM Architecture
25  *     Document number: ARM IHI 0038A (current through ABI r2.09)
26  *     Date of Issue: 25th January 2007, reissued 30th November 2012
27  *     http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
28  */
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 // Converts a prel31 avlue to lldb::addr_t with sign extension
34 static addr_t Prel31ToAddr(uint32_t prel31) {
35   addr_t res = prel31;
36   if (prel31 & (1 << 30))
37     res |= 0xffffffff80000000ULL;
38   return res;
39 }
40
41 ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a,
42                                             uint32_t d)
43     : file_address(f), address(a), data(d) {}
44
45 bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const {
46   return address < other.address;
47 }
48
49 ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx,
50                              SectionSP &arm_extab)
51     : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx),
52       m_arm_extab_sp(arm_extab) {
53   objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data);
54   objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data);
55
56   addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress();
57
58   offset_t offset = 0;
59   while (m_arm_exidx_data.ValidOffset(offset)) {
60     lldb::addr_t file_addr = exidx_base_addr + offset;
61     lldb::addr_t addr = exidx_base_addr + (addr_t)offset +
62                         Prel31ToAddr(m_arm_exidx_data.GetU32(&offset));
63     uint32_t data = m_arm_exidx_data.GetU32(&offset);
64     m_exidx_entries.emplace_back(file_addr, addr, data);
65   }
66
67   // Sort the entries in the exidx section. The entries should be sorted inside
68   // the section but some old compiler isn't sorted them.
69   std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
70 }
71
72 ArmUnwindInfo::~ArmUnwindInfo() {}
73
74 // Read a byte from the unwind instruction stream with the given offset. Custom
75 // function is required because have to red in order of significance within
76 // their containing word (most significant byte first) and in increasing word
77 // address order.
78 uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data,
79                                        uint16_t offset) const {
80   uint32_t value = data[offset / 4];
81   if (m_byte_order != endian::InlHostByteOrder())
82     value = llvm::ByteSwap_32(value);
83   return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
84 }
85
86 uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset,
87                                    uint16_t max_offset) const {
88   uint64_t result = 0;
89   uint8_t shift = 0;
90   while (offset < max_offset) {
91     uint8_t byte = GetByteAtOffset(data, offset++);
92     result |= (uint64_t)(byte & 0x7f) << shift;
93     if ((byte & 0x80) == 0)
94       break;
95     shift += 7;
96   }
97   return result;
98 }
99
100 bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr,
101                                   UnwindPlan &unwind_plan) {
102   const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr);
103   if (data == nullptr)
104     return false; // No unwind information for the function
105
106   if (data[0] == 0x1)
107     return false; // EXIDX_CANTUNWIND
108
109   uint16_t byte_count = 0;
110   uint16_t byte_offset = 0;
111   if (data[0] & 0x80000000) {
112     switch ((data[0] >> 24) & 0x0f) {
113     case 0:
114       byte_count = 4;
115       byte_offset = 1;
116       break;
117     case 1:
118     case 2:
119       byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
120       byte_offset = 2;
121       break;
122     default:
123       // Unhandled personality routine index
124       return false;
125     }
126   } else {
127     byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
128     byte_offset = 5;
129   }
130
131   uint8_t vsp_reg = dwarf_sp;
132   int32_t vsp = 0;
133   std::vector<std::pair<uint32_t, int32_t>>
134       register_offsets; // register -> (offset from vsp_reg)
135
136   while (byte_offset < byte_count) {
137     uint8_t byte1 = GetByteAtOffset(data, byte_offset++);
138     if ((byte1 & 0xc0) == 0x00) {
139       // 00xxxxxx
140       // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
141       vsp += ((byte1 & 0x3f) << 2) + 4;
142     } else if ((byte1 & 0xc0) == 0x40) {
143       // 01xxxxxx
144       // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
145       vsp -= ((byte1 & 0x3f) << 2) + 4;
146     } else if ((byte1 & 0xf0) == 0x80) {
147       if (byte_offset >= byte_count)
148         return false;
149
150       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
151       if (byte1 == 0x80 && byte2 == 0) {
152         // 10000000 00000000
153         // Refuse to unwind (for example, out of a cleanup) (see remark a)
154         return false;
155       } else {
156         // 1000iiii iiiiiiii (i not all 0)
157         // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see
158         // remark b)
159         uint16_t regs = ((byte1 & 0x0f) << 8) | byte2;
160         for (uint8_t i = 0; i < 12; ++i) {
161           if (regs & (1 << i)) {
162             register_offsets.emplace_back(dwarf_r4 + i, vsp);
163             vsp += 4;
164           }
165         }
166       }
167     } else if ((byte1 & 0xff) == 0x9d) {
168       // 10011101
169       // Reserved as prefix for ARM register to register moves
170       return false;
171     } else if ((byte1 & 0xff) == 0x9f) {
172       // 10011111
173       // Reserved as prefix for Intel Wireless MMX register to register moves
174       return false;
175     } else if ((byte1 & 0xf0) == 0x90) {
176       // 1001nnnn (nnnn != 13,15)
177       // Set vsp = r[nnnn]
178       vsp_reg = dwarf_r0 + (byte1 & 0x0f);
179     } else if ((byte1 & 0xf8) == 0xa0) {
180       // 10100nnn
181       // Pop r4-r[4+nnn]
182       uint8_t n = byte1 & 0x7;
183       for (uint8_t i = 0; i <= n; ++i) {
184         register_offsets.emplace_back(dwarf_r4 + i, vsp);
185         vsp += 4;
186       }
187     } else if ((byte1 & 0xf8) == 0xa8) {
188       // 10101nnn
189       // Pop r4-r[4+nnn], r14
190       uint8_t n = byte1 & 0x7;
191       for (uint8_t i = 0; i <= n; ++i) {
192         register_offsets.emplace_back(dwarf_r4 + i, vsp);
193         vsp += 4;
194       }
195
196       register_offsets.emplace_back(dwarf_lr, vsp);
197       vsp += 4;
198     } else if ((byte1 & 0xff) == 0xb0) {
199       // 10110000
200       // Finish (see remark c)
201       break;
202     } else if ((byte1 & 0xff) == 0xb1) {
203       if (byte_offset >= byte_count)
204         return false;
205
206       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
207       if ((byte2 & 0xff) == 0x00) {
208         // 10110001 00000000
209         // Spare (see remark f)
210         return false;
211       } else if ((byte2 & 0xf0) == 0x00) {
212         // 10110001 0000iiii (i not all 0)
213         // Pop integer registers under mask {r3, r2, r1, r0}
214         for (uint8_t i = 0; i < 4; ++i) {
215           if (byte2 & (1 << i)) {
216             register_offsets.emplace_back(dwarf_r0 + i, vsp);
217             vsp += 4;
218           }
219         }
220       } else {
221         // 10110001 xxxxyyyy
222         // Spare (xxxx != 0000)
223         return false;
224       }
225     } else if ((byte1 & 0xff) == 0xb2) {
226       // 10110010 uleb128
227       // vsp = vsp + 0x204+ (uleb128 << 2)
228       uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
229       vsp += 0x204 + (uleb128 << 2);
230     } else if ((byte1 & 0xff) == 0xb3) {
231       // 10110011 sssscccc
232       // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if)
233       // by FSTMFDX (see remark d)
234       if (byte_offset >= byte_count)
235         return false;
236
237       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
238       uint8_t s = (byte2 & 0xf0) >> 4;
239       uint8_t c = (byte2 & 0x0f) >> 0;
240       for (uint8_t i = 0; i <= c; ++i) {
241         register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
242         vsp += 8;
243       }
244       vsp += 4;
245     } else if ((byte1 & 0xfc) == 0xb4) {
246       // 101101nn
247       // Spare (was Pop FPA)
248       return false;
249     } else if ((byte1 & 0xf8) == 0xb8) {
250       // 10111nnn
251       // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
252       // FSTMFDX (see remark d)
253       uint8_t n = byte1 & 0x07;
254       for (uint8_t i = 0; i <= n; ++i) {
255         register_offsets.emplace_back(dwarf_d8 + i, vsp);
256         vsp += 8;
257       }
258       vsp += 4;
259     } else if ((byte1 & 0xf8) == 0xc0) {
260       // 11000nnn (nnn != 6,7)
261       // Intel Wireless MMX pop wR[10]-wR[10+nnn]
262
263       // 11000110 sssscccc
264       // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)
265
266       // 11000111 00000000
267       // Spare
268
269       // 11000111 0000iiii
270       // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
271
272       // 11000111 xxxxyyyy
273       // Spare (xxxx != 0000)
274
275       return false;
276     } else if ((byte1 & 0xff) == 0xc8) {
277       // 11001000 sssscccc
278       // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved
279       // (as if) by FSTMFDD (see remarks d,e)
280       if (byte_offset >= byte_count)
281         return false;
282
283       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
284       uint8_t s = (byte2 & 0xf0) >> 4;
285       uint8_t c = (byte2 & 0x0f) >> 0;
286       for (uint8_t i = 0; i <= c; ++i) {
287         register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
288         vsp += 8;
289       }
290     } else if ((byte1 & 0xff) == 0xc9) {
291       // 11001001 sssscccc
292       // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if)
293       // by FSTMFDD (see remark d)
294       if (byte_offset >= byte_count)
295         return false;
296
297       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
298       uint8_t s = (byte2 & 0xf0) >> 4;
299       uint8_t c = (byte2 & 0x0f) >> 0;
300       for (uint8_t i = 0; i <= c; ++i) {
301         register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
302         vsp += 8;
303       }
304     } else if ((byte1 & 0xf8) == 0xc8) {
305       // 11001yyy
306       // Spare (yyy != 000, 001)
307       return false;
308     } else if ((byte1 & 0xf8) == 0xc0) {
309       // 11010nnn
310       // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
311       // FSTMFDD (see remark d)
312       uint8_t n = byte1 & 0x07;
313       for (uint8_t i = 0; i <= n; ++i) {
314         register_offsets.emplace_back(dwarf_d8 + i, vsp);
315         vsp += 8;
316       }
317     } else if ((byte1 & 0xc0) == 0xc0) {
318       // 11xxxyyy Spare (xxx != 000, 001, 010)
319       return false;
320     } else {
321       return false;
322     }
323   }
324
325   UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
326   row->SetOffset(0);
327   row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);
328
329   bool have_location_for_pc = false;
330   for (const auto &offset : register_offsets) {
331     have_location_for_pc |= offset.first == dwarf_pc;
332     row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp,
333                                               true);
334   }
335
336   if (!have_location_for_pc) {
337     UnwindPlan::Row::RegisterLocation lr_location;
338     if (row->GetRegisterInfo(dwarf_lr, lr_location))
339       row->SetRegisterInfo(dwarf_pc, lr_location);
340     else
341       row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
342   }
343
344   unwind_plan.AppendRow(row);
345   unwind_plan.SetSourceName("ARM.exidx unwind info");
346   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
347   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
348   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
349
350   return true;
351 }
352
353 const uint8_t *
354 ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) {
355   auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(),
356                              ArmExidxEntry{0, addr.GetFileAddress(), 0});
357   if (it == m_exidx_entries.begin())
358     return nullptr;
359   --it;
360
361   if (it->data == 0x1)
362     return nullptr; // EXIDX_CANTUNWIND
363
364   if (it->data & 0x80000000)
365     return (const uint8_t *)&it->data;
366
367   addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data);
368   return m_arm_extab_data.GetDataStart() +
369          (data_file_addr - m_arm_extab_sp->GetFileAddress());
370 }