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