• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #include <stdint.h>
18 
19 #include <deque>
20 #include <string>
21 
22 #include <android-base/stringprintf.h>
23 
24 #include <unwindstack/Log.h>
25 #include <unwindstack/MachineArm.h>
26 #include <unwindstack/Memory.h>
27 #include <unwindstack/RegsArm.h>
28 
29 #include "ArmExidx.h"
30 #include "Check.h"
31 
32 namespace unwindstack {
33 
LogRawData()34 void ArmExidx::LogRawData() {
35   std::string log_str("Raw Data:");
36   for (const uint8_t data : data_) {
37     log_str += android::base::StringPrintf(" 0x%02x", data);
38   }
39   log(log_indent_, log_str.c_str());
40 }
41 
ExtractEntryData(uint32_t entry_offset)42 bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
43   data_.clear();
44   status_ = ARM_STATUS_NONE;
45 
46   if (entry_offset & 1) {
47     // The offset needs to be at least two byte aligned.
48     status_ = ARM_STATUS_INVALID_ALIGNMENT;
49     return false;
50   }
51 
52   // Each entry is a 32 bit prel31 offset followed by 32 bits
53   // of unwind information. If bit 31 of the unwind data is zero,
54   // then this is a prel31 offset to the start of the unwind data.
55   // If the unwind data is 1, then this is a cant unwind entry.
56   // Otherwise, this data is the compact form of the unwind information.
57   uint32_t data;
58   if (!elf_memory_->Read32(entry_offset + 4, &data)) {
59     status_ = ARM_STATUS_READ_FAILED;
60     status_address_ = entry_offset + 4;
61     return false;
62   }
63   if (data == 1) {
64     // This is a CANT UNWIND entry.
65     status_ = ARM_STATUS_NO_UNWIND;
66     if (log_) {
67       log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
68       log(log_indent_, "[cantunwind]");
69     }
70     return false;
71   }
72 
73   if (data & (1UL << 31)) {
74     // This is a compact table entry.
75     if ((data >> 24) & 0xf) {
76       // This is a non-zero index, this code doesn't support
77       // other formats.
78       status_ = ARM_STATUS_INVALID_PERSONALITY;
79       return false;
80     }
81     data_.push_back((data >> 16) & 0xff);
82     data_.push_back((data >> 8) & 0xff);
83     uint8_t last_op = data & 0xff;
84     data_.push_back(last_op);
85     if (last_op != ARM_OP_FINISH) {
86       // If this didn't end with a finish op, add one.
87       data_.push_back(ARM_OP_FINISH);
88     }
89     if (log_) {
90       LogRawData();
91     }
92     return true;
93   }
94 
95   // Get the address of the ops.
96   // Sign extend the data value if necessary.
97   int32_t signed_data = static_cast<int32_t>(data << 1) >> 1;
98   uint32_t addr = (entry_offset + 4) + signed_data;
99   if (!elf_memory_->Read32(addr, &data)) {
100     status_ = ARM_STATUS_READ_FAILED;
101     status_address_ = addr;
102     return false;
103   }
104 
105   size_t num_table_words;
106   if (data & (1UL << 31)) {
107     // Compact model.
108     switch ((data >> 24) & 0xf) {
109     case 0:
110       num_table_words = 0;
111       data_.push_back((data >> 16) & 0xff);
112       break;
113     case 1:
114     case 2:
115       num_table_words = (data >> 16) & 0xff;
116       addr += 4;
117       break;
118     default:
119       // Only a personality of 0, 1, 2 is valid.
120       status_ = ARM_STATUS_INVALID_PERSONALITY;
121       return false;
122     }
123     data_.push_back((data >> 8) & 0xff);
124     data_.push_back(data & 0xff);
125   } else {
126     // Generic model.
127 
128     // Skip the personality routine data, it doesn't contain any data
129     // needed to decode the unwind information.
130     addr += 4;
131     if (!elf_memory_->Read32(addr, &data)) {
132       status_ = ARM_STATUS_READ_FAILED;
133       status_address_ = addr;
134       return false;
135     }
136     num_table_words = (data >> 24) & 0xff;
137     data_.push_back((data >> 16) & 0xff);
138     data_.push_back((data >> 8) & 0xff);
139     data_.push_back(data & 0xff);
140     addr += 4;
141   }
142 
143   if (num_table_words > 5) {
144     status_ = ARM_STATUS_MALFORMED;
145     return false;
146   }
147 
148   for (size_t i = 0; i < num_table_words; i++) {
149     if (!elf_memory_->Read32(addr, &data)) {
150       status_ = ARM_STATUS_READ_FAILED;
151       status_address_ = addr;
152       return false;
153     }
154     data_.push_back((data >> 24) & 0xff);
155     data_.push_back((data >> 16) & 0xff);
156     data_.push_back((data >> 8) & 0xff);
157     data_.push_back(data & 0xff);
158     addr += 4;
159   }
160 
161   if (data_.back() != ARM_OP_FINISH) {
162     // If this didn't end with a finish op, add one.
163     data_.push_back(ARM_OP_FINISH);
164   }
165 
166   if (log_) {
167     LogRawData();
168   }
169   return true;
170 }
171 
GetByte(uint8_t * byte)172 inline bool ArmExidx::GetByte(uint8_t* byte) {
173   if (data_.empty()) {
174     status_ = ARM_STATUS_TRUNCATED;
175     return false;
176   }
177   *byte = data_.front();
178   data_.pop_front();
179   return true;
180 }
181 
DecodePrefix_10_00(uint8_t byte)182 inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
183   CHECK((byte >> 4) == 0x8);
184 
185   uint16_t registers = (byte & 0xf) << 8;
186   if (!GetByte(&byte)) {
187     return false;
188   }
189 
190   registers |= byte;
191   if (registers == 0) {
192     // 10000000 00000000: Refuse to unwind
193     if (log_) {
194       log(log_indent_, "Refuse to unwind");
195     }
196     status_ = ARM_STATUS_NO_UNWIND;
197     return false;
198   }
199   // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
200   if (log_) {
201     bool add_comma = false;
202     std::string msg = "pop {";
203     for (size_t i = 0; i < 12; i++) {
204       if (registers & (1 << i)) {
205         if (add_comma) {
206           msg += ", ";
207         }
208         msg += android::base::StringPrintf("r%zu", i + 4);
209         add_comma = true;
210       }
211     }
212     log(log_indent_, "%s}", msg.c_str());
213     if (log_skip_execution_) {
214       return true;
215     }
216   }
217 
218   registers <<= 4;
219   for (size_t reg = 4; reg < 16; reg++) {
220     if (registers & (1 << reg)) {
221       if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
222         status_ = ARM_STATUS_READ_FAILED;
223         status_address_ = cfa_;
224         return false;
225       }
226       cfa_ += 4;
227     }
228   }
229 
230   // If the sp register is modified, change the cfa value.
231   if (registers & (1 << ARM_REG_SP)) {
232     cfa_ = (*regs_)[ARM_REG_SP];
233   }
234 
235   // Indicate if the pc register was set.
236   if (registers & (1 << ARM_REG_PC)) {
237     pc_set_ = true;
238   }
239   return true;
240 }
241 
DecodePrefix_10_01(uint8_t byte)242 inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
243   CHECK((byte >> 4) == 0x9);
244 
245   uint8_t bits = byte & 0xf;
246   if (bits == 13 || bits == 15) {
247     // 10011101: Reserved as prefix for ARM register to register moves
248     // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
249     if (log_) {
250       log(log_indent_, "[Reserved]");
251     }
252     status_ = ARM_STATUS_RESERVED;
253     return false;
254   }
255   // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
256   if (log_) {
257     log(log_indent_, "vsp = r%d", bits);
258     if (log_skip_execution_) {
259       return true;
260     }
261   }
262   // It is impossible for bits to be larger than the total number of
263   // arm registers, so don't bother checking if bits is a valid register.
264   cfa_ = (*regs_)[bits];
265   return true;
266 }
267 
DecodePrefix_10_10(uint8_t byte)268 inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
269   CHECK((byte >> 4) == 0xa);
270 
271   // 10100nnn: Pop r4-r[4+nnn]
272   // 10101nnn: Pop r4-r[4+nnn], r14
273   if (log_) {
274     std::string msg = "pop {r4";
275     uint8_t end_reg = byte & 0x7;
276     if (end_reg) {
277       msg += android::base::StringPrintf("-r%d", 4 + end_reg);
278     }
279     if (byte & 0x8) {
280       log(log_indent_, "%s, r14}", msg.c_str());
281     } else {
282       log(log_indent_, "%s}", msg.c_str());
283     }
284     if (log_skip_execution_) {
285       return true;
286     }
287   }
288 
289   for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
290     if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
291       status_ = ARM_STATUS_READ_FAILED;
292       status_address_ = cfa_;
293       return false;
294     }
295     cfa_ += 4;
296   }
297   if (byte & 0x8) {
298     if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
299       status_ = ARM_STATUS_READ_FAILED;
300       status_address_ = cfa_;
301       return false;
302     }
303     cfa_ += 4;
304   }
305   return true;
306 }
307 
DecodePrefix_10_11_0000()308 inline bool ArmExidx::DecodePrefix_10_11_0000() {
309   // 10110000: Finish
310   if (log_) {
311     log(log_indent_, "finish");
312     if (log_skip_execution_) {
313       status_ = ARM_STATUS_FINISH;
314       return false;
315     }
316   }
317   status_ = ARM_STATUS_FINISH;
318   return false;
319 }
320 
DecodePrefix_10_11_0001()321 inline bool ArmExidx::DecodePrefix_10_11_0001() {
322   uint8_t byte;
323   if (!GetByte(&byte)) {
324     return false;
325   }
326 
327   if (byte == 0) {
328     // 10110001 00000000: Spare
329     if (log_) {
330       log(log_indent_, "Spare");
331     }
332     status_ = ARM_STATUS_SPARE;
333     return false;
334   }
335   if (byte >> 4) {
336     // 10110001 xxxxyyyy: Spare (xxxx != 0000)
337     if (log_) {
338       log(log_indent_, "Spare");
339     }
340     status_ = ARM_STATUS_SPARE;
341     return false;
342   }
343 
344   // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
345   if (log_) {
346     bool add_comma = false;
347     std::string msg = "pop {";
348     for (size_t i = 0; i < 4; i++) {
349       if (byte & (1 << i)) {
350         if (add_comma) {
351           msg += ", ";
352         }
353         msg += android::base::StringPrintf("r%zu", i);
354         add_comma = true;
355       }
356     }
357     log(log_indent_, "%s}", msg.c_str());
358     if (log_skip_execution_) {
359       return true;
360     }
361   }
362 
363   for (size_t reg = 0; reg < 4; reg++) {
364     if (byte & (1 << reg)) {
365       if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
366         status_ = ARM_STATUS_READ_FAILED;
367         status_address_ = cfa_;
368         return false;
369       }
370       cfa_ += 4;
371     }
372   }
373   return true;
374 }
375 
DecodePrefix_10_11_0010()376 inline bool ArmExidx::DecodePrefix_10_11_0010() {
377   // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
378   uint32_t result = 0;
379   uint32_t shift = 0;
380   uint8_t byte;
381   do {
382     if (!GetByte(&byte)) {
383       return false;
384     }
385 
386     result |= (byte & 0x7f) << shift;
387     shift += 7;
388   } while (byte & 0x80);
389   result <<= 2;
390   if (log_) {
391     log(log_indent_, "vsp = vsp + %d", 0x204 + result);
392     if (log_skip_execution_) {
393       return true;
394     }
395   }
396   cfa_ += 0x204 + result;
397   return true;
398 }
399 
DecodePrefix_10_11_0011()400 inline bool ArmExidx::DecodePrefix_10_11_0011() {
401   // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
402   uint8_t byte;
403   if (!GetByte(&byte)) {
404     return false;
405   }
406 
407   if (log_) {
408     uint8_t start_reg = byte >> 4;
409     std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
410     uint8_t end_reg = start_reg + (byte & 0xf);
411     if (end_reg) {
412       msg += android::base::StringPrintf("-d%d", end_reg);
413     }
414     log(log_indent_, "%s}", msg.c_str());
415     if (log_skip_execution_) {
416       return true;
417     }
418   }
419   cfa_ += (byte & 0xf) * 8 + 12;
420   return true;
421 }
422 
DecodePrefix_10_11_01nn()423 inline bool ArmExidx::DecodePrefix_10_11_01nn() {
424   // 101101nn: Spare
425   if (log_) {
426     log(log_indent_, "Spare");
427   }
428   status_ = ARM_STATUS_SPARE;
429   return false;
430 }
431 
DecodePrefix_10_11_1nnn(uint8_t byte)432 inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
433   CHECK((byte & ~0x07) == 0xb8);
434 
435   // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
436   if (log_) {
437     std::string msg = "pop {d8";
438     uint8_t last_reg = (byte & 0x7);
439     if (last_reg) {
440       msg += android::base::StringPrintf("-d%d", last_reg + 8);
441     }
442     log(log_indent_, "%s}", msg.c_str());
443     if (log_skip_execution_) {
444       return true;
445     }
446   }
447   // Only update the cfa.
448   cfa_ += (byte & 0x7) * 8 + 12;
449   return true;
450 }
451 
DecodePrefix_10(uint8_t byte)452 inline bool ArmExidx::DecodePrefix_10(uint8_t byte) {
453   CHECK((byte >> 6) == 0x2);
454 
455   switch ((byte >> 4) & 0x3) {
456   case 0:
457     return DecodePrefix_10_00(byte);
458   case 1:
459     return DecodePrefix_10_01(byte);
460   case 2:
461     return DecodePrefix_10_10(byte);
462   default:
463     switch (byte & 0xf) {
464     case 0:
465       return DecodePrefix_10_11_0000();
466     case 1:
467       return DecodePrefix_10_11_0001();
468     case 2:
469       return DecodePrefix_10_11_0010();
470     case 3:
471       return DecodePrefix_10_11_0011();
472     default:
473       if (byte & 0x8) {
474         return DecodePrefix_10_11_1nnn(byte);
475       } else {
476         return DecodePrefix_10_11_01nn();
477       }
478     }
479   }
480 }
481 
DecodePrefix_11_000(uint8_t byte)482 inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
483   CHECK((byte & ~0x07) == 0xc0);
484 
485   uint8_t bits = byte & 0x7;
486   if (bits == 6) {
487     if (!GetByte(&byte)) {
488       return false;
489     }
490 
491     // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
492     if (log_) {
493       uint8_t start_reg = byte >> 4;
494       std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
495       uint8_t end_reg = byte & 0xf;
496       if (end_reg) {
497         msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
498       }
499       log(log_indent_, "%s}", msg.c_str());
500       if (log_skip_execution_) {
501         return true;
502       }
503     }
504     // Only update the cfa.
505     cfa_ += (byte & 0xf) * 8 + 8;
506   } else if (bits == 7) {
507     if (!GetByte(&byte)) {
508       return false;
509     }
510 
511     if (byte == 0) {
512       // 11000111 00000000: Spare
513       if (log_) {
514         log(log_indent_, "Spare");
515       }
516       status_ = ARM_STATUS_SPARE;
517       return false;
518     } else if ((byte >> 4) == 0) {
519       // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
520       if (log_) {
521         bool add_comma = false;
522         std::string msg = "pop {";
523         for (size_t i = 0; i < 4; i++) {
524           if (byte & (1 << i)) {
525             if (add_comma) {
526               msg += ", ";
527             }
528             msg += android::base::StringPrintf("wCGR%zu", i);
529             add_comma = true;
530           }
531         }
532         log(log_indent_, "%s}", msg.c_str());
533       }
534       // Only update the cfa.
535       cfa_ += __builtin_popcount(byte) * 4;
536     } else {
537       // 11000111 xxxxyyyy: Spare (xxxx != 0000)
538       if (log_) {
539         log(log_indent_, "Spare");
540       }
541       status_ = ARM_STATUS_SPARE;
542       return false;
543     }
544   } else {
545     // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
546     if (log_) {
547       std::string msg = "pop {wR10";
548       uint8_t nnn = byte & 0x7;
549       if (nnn) {
550         msg += android::base::StringPrintf("-wR%d", 10 + nnn);
551       }
552       log(log_indent_, "%s}", msg.c_str());
553       if (log_skip_execution_) {
554         return true;
555       }
556     }
557     // Only update the cfa.
558     cfa_ += (byte & 0x7) * 8 + 8;
559   }
560   return true;
561 }
562 
DecodePrefix_11_001(uint8_t byte)563 inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
564   CHECK((byte & ~0x07) == 0xc8);
565 
566   uint8_t bits = byte & 0x7;
567   if (bits == 0) {
568     // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH
569     if (!GetByte(&byte)) {
570       return false;
571     }
572 
573     if (log_) {
574       uint8_t start_reg = byte >> 4;
575       std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
576       uint8_t end_reg = byte & 0xf;
577       if (end_reg) {
578         msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
579       }
580       log(log_indent_, "%s}", msg.c_str());
581       if (log_skip_execution_) {
582         return true;
583       }
584     }
585     // Only update the cfa.
586     cfa_ += (byte & 0xf) * 8 + 8;
587   } else if (bits == 1) {
588     // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH
589     if (!GetByte(&byte)) {
590       return false;
591     }
592 
593     if (log_) {
594       uint8_t start_reg = byte >> 4;
595       std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
596       uint8_t end_reg = byte & 0xf;
597       if (end_reg) {
598         msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
599       }
600       log(log_indent_, "%s}", msg.c_str());
601       if (log_skip_execution_) {
602         return true;
603       }
604     }
605     // Only update the cfa.
606     cfa_ += (byte & 0xf) * 8 + 8;
607   } else {
608     // 11001yyy: Spare (yyy != 000, 001)
609     if (log_) {
610       log(log_indent_, "Spare");
611     }
612     status_ = ARM_STATUS_SPARE;
613     return false;
614   }
615   return true;
616 }
617 
DecodePrefix_11_010(uint8_t byte)618 inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
619   CHECK((byte & ~0x07) == 0xd0);
620 
621   // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
622   if (log_) {
623     std::string msg = "pop {d8";
624     uint8_t end_reg = byte & 0x7;
625     if (end_reg) {
626       msg += android::base::StringPrintf("-d%d", 8 + end_reg);
627     }
628     log(log_indent_, "%s}", msg.c_str());
629     if (log_skip_execution_) {
630       return true;
631     }
632   }
633   cfa_ += (byte & 0x7) * 8 + 8;
634   return true;
635 }
636 
DecodePrefix_11(uint8_t byte)637 inline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
638   CHECK((byte >> 6) == 0x3);
639 
640   switch ((byte >> 3) & 0x7) {
641   case 0:
642     return DecodePrefix_11_000(byte);
643   case 1:
644     return DecodePrefix_11_001(byte);
645   case 2:
646     return DecodePrefix_11_010(byte);
647   default:
648     // 11xxxyyy: Spare (xxx != 000, 001, 010)
649     if (log_) {
650       log(log_indent_, "Spare");
651     }
652     status_ = ARM_STATUS_SPARE;
653     return false;
654   }
655 }
656 
Decode()657 bool ArmExidx::Decode() {
658   status_ = ARM_STATUS_NONE;
659   uint8_t byte;
660   if (!GetByte(&byte)) {
661     return false;
662   }
663 
664   switch (byte >> 6) {
665   case 0:
666     // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
667     if (log_) {
668       log(log_indent_, "vsp = vsp + %d", ((byte & 0x3f) << 2) + 4);
669       if (log_skip_execution_) {
670         break;
671       }
672     }
673     cfa_ += ((byte & 0x3f) << 2) + 4;
674     break;
675   case 1:
676     // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
677     if (log_) {
678       log(log_indent_, "vsp = vsp - %d", ((byte & 0x3f) << 2) + 4);
679       if (log_skip_execution_) {
680         break;
681       }
682     }
683     cfa_ -= ((byte & 0x3f) << 2) + 4;
684     break;
685   case 2:
686     return DecodePrefix_10(byte);
687   default:
688     return DecodePrefix_11(byte);
689   }
690   return true;
691 }
692 
Eval()693 bool ArmExidx::Eval() {
694   pc_set_ = false;
695   while (Decode());
696   return status_ == ARM_STATUS_FINISH;
697 }
698 
699 }  // namespace unwindstack
700