]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/ArmUnwindInfo.cpp
Merge ^/head r321239 through r321306.
[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(const 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
69   // some old compiler isn't sorted them.
70   std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
71 }
72
73 ArmUnwindInfo::~ArmUnwindInfo() {}
74
75 // Read a byte from the unwind instruction stream with the given offset.
76 // Custom function is required because have to red in order of significance
77 // within their containing
78 // word (most significant byte first) and in increasing word address order.
79 uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data,
80                                        uint16_t offset) const {
81   uint32_t value = data[offset / 4];
82   if (m_byte_order != endian::InlHostByteOrder())
83     value = llvm::ByteSwap_32(value);
84   return (value >> ((3 - (offset % 4)) * 8)) & 0xff;
85 }
86
87 uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset,
88                                    uint16_t max_offset) const {
89   uint64_t result = 0;
90   uint8_t shift = 0;
91   while (offset < max_offset) {
92     uint8_t byte = GetByteAtOffset(data, offset++);
93     result |= (uint64_t)(byte & 0x7f) << shift;
94     if ((byte & 0x80) == 0)
95       break;
96     shift += 7;
97   }
98   return result;
99 }
100
101 bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr,
102                                   UnwindPlan &unwind_plan) {
103   const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr);
104   if (data == nullptr)
105     return false; // No unwind information for the function
106
107   if (data[0] == 0x1)
108     return false; // EXIDX_CANTUNWIND
109
110   uint16_t byte_count = 0;
111   uint16_t byte_offset = 0;
112   if (data[0] & 0x80000000) {
113     switch ((data[0] >> 24) & 0x0f) {
114     case 0:
115       byte_count = 4;
116       byte_offset = 1;
117       break;
118     case 1:
119     case 2:
120       byte_count = 4 * ((data[0] >> 16) & 0xff) + 4;
121       byte_offset = 2;
122       break;
123     default:
124       // Unhandled personality routine index
125       return false;
126     }
127   } else {
128     byte_count = 4 * ((data[1] >> 24) & 0xff) + 8;
129     byte_offset = 5;
130   }
131
132   uint8_t vsp_reg = dwarf_sp;
133   int32_t vsp = 0;
134   std::vector<std::pair<uint32_t, int32_t>>
135       register_offsets; // register -> (offset from vsp_reg)
136
137   while (byte_offset < byte_count) {
138     uint8_t byte1 = GetByteAtOffset(data, byte_offset++);
139     if ((byte1 & 0xc0) == 0x00) {
140       // 00xxxxxx
141       // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive
142       vsp += ((byte1 & 0x3f) << 2) + 4;
143     } else if ((byte1 & 0xc0) == 0x40) {
144       // 01xxxxxx
145       // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive
146       vsp -= ((byte1 & 0x3f) << 2) + 4;
147     } else if ((byte1 & 0xf0) == 0x80) {
148       if (byte_offset >= byte_count)
149         return false;
150
151       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
152       if (byte1 == 0x80 && byte2 == 0) {
153         // 10000000 00000000
154         // Refuse to unwind (for example, out of a cleanup) (see remark a)
155         return false;
156       } else {
157         // 1000iiii iiiiiiii (i not all 0)
158         // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see
159         // remark b)
160         uint16_t regs = ((byte1 & 0x0f) << 8) | byte2;
161         for (uint8_t i = 0; i < 12; ++i) {
162           if (regs & (1 << i)) {
163             register_offsets.emplace_back(dwarf_r4 + i, vsp);
164             vsp += 4;
165           }
166         }
167       }
168     } else if ((byte1 & 0xff) == 0x9d) {
169       // 10011101
170       // Reserved as prefix for ARM register to register moves
171       return false;
172     } else if ((byte1 & 0xff) == 0x9f) {
173       // 10011111
174       // Reserved as prefix for Intel Wireless MMX register to register moves
175       return false;
176     } else if ((byte1 & 0xf0) == 0x90) {
177       // 1001nnnn (nnnn != 13,15)
178       // Set vsp = r[nnnn]
179       vsp_reg = dwarf_r0 + (byte1 & 0x0f);
180     } else if ((byte1 & 0xf8) == 0xa0) {
181       // 10100nnn
182       // Pop r4-r[4+nnn]
183       uint8_t n = byte1 & 0x7;
184       for (uint8_t i = 0; i <= n; ++i) {
185         register_offsets.emplace_back(dwarf_r4 + i, vsp);
186         vsp += 4;
187       }
188     } else if ((byte1 & 0xf8) == 0xa8) {
189       // 10101nnn
190       // Pop r4-r[4+nnn], r14
191       uint8_t n = byte1 & 0x7;
192       for (uint8_t i = 0; i <= n; ++i) {
193         register_offsets.emplace_back(dwarf_r4 + i, vsp);
194         vsp += 4;
195       }
196
197       register_offsets.emplace_back(dwarf_lr, vsp);
198       vsp += 4;
199     } else if ((byte1 & 0xff) == 0xb0) {
200       // 10110000
201       // Finish (see remark c)
202       break;
203     } else if ((byte1 & 0xff) == 0xb1) {
204       if (byte_offset >= byte_count)
205         return false;
206
207       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
208       if ((byte2 & 0xff) == 0x00) {
209         // 10110001 00000000
210         // Spare (see remark f)
211         return false;
212       } else if ((byte2 & 0xf0) == 0x00) {
213         // 10110001 0000iiii (i not all 0)
214         // Pop integer registers under mask {r3, r2, r1, r0}
215         for (uint8_t i = 0; i < 4; ++i) {
216           if (byte2 & (1 << i)) {
217             register_offsets.emplace_back(dwarf_r0 + i, vsp);
218             vsp += 4;
219           }
220         }
221       } else {
222         // 10110001 xxxxyyyy
223         // Spare (xxxx != 0000)
224         return false;
225       }
226     } else if ((byte1 & 0xff) == 0xb2) {
227       // 10110010 uleb128
228       // vsp = vsp + 0x204+ (uleb128 << 2)
229       uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count);
230       vsp += 0x204 + (uleb128 << 2);
231     } else if ((byte1 & 0xff) == 0xb3) {
232       // 10110011 sssscccc
233       // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if)
234       // by FSTMFDX (see remark d)
235       if (byte_offset >= byte_count)
236         return false;
237
238       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
239       uint8_t s = (byte2 & 0xf0) >> 4;
240       uint8_t c = (byte2 & 0x0f) >> 0;
241       for (uint8_t i = 0; i <= c; ++i) {
242         register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
243         vsp += 8;
244       }
245       vsp += 4;
246     } else if ((byte1 & 0xfc) == 0xb4) {
247       // 101101nn
248       // Spare (was Pop FPA)
249       return false;
250     } else if ((byte1 & 0xf8) == 0xb8) {
251       // 10111nnn
252       // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
253       // FSTMFDX (see remark d)
254       uint8_t n = byte1 & 0x07;
255       for (uint8_t i = 0; i <= n; ++i) {
256         register_offsets.emplace_back(dwarf_d8 + i, vsp);
257         vsp += 8;
258       }
259       vsp += 4;
260     } else if ((byte1 & 0xf8) == 0xc0) {
261       // 11000nnn (nnn != 6,7)
262       // Intel Wireless MMX pop wR[10]-wR[10+nnn]
263
264       // 11000110 sssscccc
265       // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e)
266
267       // 11000111 00000000
268       // Spare
269
270       // 11000111 0000iiii
271       // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
272
273       // 11000111 xxxxyyyy
274       // Spare (xxxx != 0000)
275
276       return false;
277     } else if ((byte1 & 0xff) == 0xc8) {
278       // 11001000 sssscccc
279       // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as
280       // if) by FSTMFDD (see remarks d,e)
281       if (byte_offset >= byte_count)
282         return false;
283
284       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
285       uint8_t s = (byte2 & 0xf0) >> 4;
286       uint8_t c = (byte2 & 0x0f) >> 0;
287       for (uint8_t i = 0; i <= c; ++i) {
288         register_offsets.emplace_back(dwarf_d16 + s + i, vsp);
289         vsp += 8;
290       }
291     } else if ((byte1 & 0xff) == 0xc9) {
292       // 11001001 sssscccc
293       // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if)
294       // by FSTMFDD (see remark d)
295       if (byte_offset >= byte_count)
296         return false;
297
298       uint8_t byte2 = GetByteAtOffset(data, byte_offset++);
299       uint8_t s = (byte2 & 0xf0) >> 4;
300       uint8_t c = (byte2 & 0x0f) >> 0;
301       for (uint8_t i = 0; i <= c; ++i) {
302         register_offsets.emplace_back(dwarf_d0 + s + i, vsp);
303         vsp += 8;
304       }
305     } else if ((byte1 & 0xf8) == 0xc8) {
306       // 11001yyy
307       // Spare (yyy != 000, 001)
308       return false;
309     } else if ((byte1 & 0xf8) == 0xc0) {
310       // 11010nnn
311       // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by
312       // FSTMFDD (see remark d)
313       uint8_t n = byte1 & 0x07;
314       for (uint8_t i = 0; i <= n; ++i) {
315         register_offsets.emplace_back(dwarf_d8 + i, vsp);
316         vsp += 8;
317       }
318     } else if ((byte1 & 0xc0) == 0xc0) {
319       // 11xxxyyy Spare (xxx != 000, 001, 010)
320       return false;
321     } else {
322       return false;
323     }
324   }
325
326   UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
327   row->SetOffset(0);
328   row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp);
329
330   bool have_location_for_pc = false;
331   for (const auto &offset : register_offsets) {
332     have_location_for_pc |= offset.first == dwarf_pc;
333     row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp,
334                                               true);
335   }
336
337   if (!have_location_for_pc) {
338     UnwindPlan::Row::RegisterLocation lr_location;
339     if (row->GetRegisterInfo(dwarf_lr, lr_location))
340       row->SetRegisterInfo(dwarf_pc, lr_location);
341     else
342       row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false);
343   }
344
345   unwind_plan.AppendRow(row);
346   unwind_plan.SetSourceName("ARM.exidx unwind info");
347   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
348   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
349   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
350
351   return true;
352 }
353
354 const uint8_t *
355 ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) {
356   auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(),
357                              ArmExidxEntry{0, addr.GetFileAddress(), 0});
358   if (it == m_exidx_entries.begin())
359     return nullptr;
360   --it;
361
362   if (it->data == 0x1)
363     return nullptr; // EXIDX_CANTUNWIND
364
365   if (it->data & 0x80000000)
366     return (const uint8_t *)&it->data;
367
368   addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data);
369   return m_arm_extab_data.GetDataStart() +
370          (data_file_addr - m_arm_extab_sp->GetFileAddress());
371 }