Add 469782 to NEWS
[valgrind.git] / coregrind / m_debuginfo / readexidx.c
blob261c9c466a85a113c12db2549cbf0119be3ab564
1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- Reading of ARM(32) EXIDX unwind information readexidx.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2014-2017 Mozilla Foundation
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 /* libunwind - a platform-independent unwind library
30 Copyright 2011 Linaro Limited
32 This file is part of libunwind.
34 Permission is hereby granted, free of charge, to any person obtaining
35 a copy of this software and associated documentation files (the
36 "Software"), to deal in the Software without restriction, including
37 without limitation the rights to use, copy, modify, merge, publish,
38 distribute, sublicense, and/or sell copies of the Software, and to
39 permit persons to whom the Software is furnished to do so, subject to
40 the following conditions:
42 The above copyright notice and this permission notice shall be
43 included in all copies or substantial portions of the Software.
45 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
54 // Copyright (c) 2010 Google Inc.
55 // All rights reserved.
57 // Redistribution and use in source and binary forms, with or without
58 // modification, are permitted provided that the following conditions are
59 // met:
61 // * Redistributions of source code must retain the above copyright
62 // notice, this list of conditions and the following disclaimer.
63 // * Redistributions in binary form must reproduce the above
64 // copyright notice, this list of conditions and the following disclaimer
65 // in the documentation and/or other materials provided with the
66 // distribution.
67 // * Neither the name of Google Inc. nor the names of its
68 // contributors may be used to endorse or promote products derived from
69 // this software without specific prior written permission.
71 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
72 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
73 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
74 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
75 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
76 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
77 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
78 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
79 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
80 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
81 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
84 // Derived originally from libunwind, with very extensive modifications.
85 /* Contributed by Julian Seward <jseward@acm.org> */
88 // This file translates EXIDX unwind information into the same format
89 // that Valgrind uses for CFI information. Hence Valgrind's CFI
90 // unwinding abilities also become usable for EXIDX.
92 // See: "Exception Handling ABI for the ARM Architecture", ARM IHI 0038A
93 // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
95 // EXIDX data is presented in two parts:
97 // * an index table. This contains two words per routine,
98 // the first of which identifies the routine, and the second
99 // of which is a reference to the unwind bytecode. If the
100 // bytecode is very compact -- 3 bytes or less -- it can be
101 // stored directly in the second word.
103 // * an area containing the unwind bytecodes.
105 // General flow is: ML_(read_exidx) iterates over all
106 // of the index table entries (pairs). For each entry, it:
108 // * calls ExtabEntryExtract to copy the bytecode out into
109 // an intermediate buffer.
111 // * uses ExtabEntryDecode to parse the intermediate
112 // buffer. Each bytecode instruction is bundled into a
113 // arm_ex_to_module::extab_data structure, and handed to ..
115 // * .. TranslateCmd, which generates the pseudo-CFI
116 // records that Valgrind stores.
118 // This file is derived from the following files in the Mozilla tree
119 // toolkit/crashreporter/google-breakpad:
120 // src/common/arm_ex_to_module.cc
121 // src/common/arm_ex_reader.cc
124 #if defined(VGA_arm)
126 #include "pub_core_basics.h"
127 #include "pub_core_libcbase.h"
128 #include "pub_core_libcprint.h"
129 #include "pub_core_libcassert.h"
130 #include "pub_core_options.h"
132 #include "priv_storage.h"
133 #include "priv_readexidx.h"
136 static void complain ( const HChar* str )
138 if (!VG_(clo_xml) && VG_(clo_verbosity) > 1)
139 VG_(message)(Vg_UserMsg,
140 " Warning: whilst reading EXIDX: %s\n", str);
144 /*------------------------------------------------------------*/
145 /*--- MemoryRange ---*/
146 /*------------------------------------------------------------*/
148 typedef struct { Addr start; SizeT len; } MemoryRange;
150 /* Initialise |mr| for [start .. start+len). Zero ranges are allowed,
151 but wraparounds are not. Returns True on success. */
152 static Bool MemoryRange__init ( /*OUT*/MemoryRange* mr,
153 const void* startV, SizeT len )
155 VG_(memset)(mr, 0, sizeof(*mr));
156 /* This relies on Addr being unsigned. */
157 Addr start = (Addr)startV;
158 if (len > 0 && start + len - 1 < start) {
159 return False;
161 mr->start = start;
162 mr->len = len;
163 return True;
166 static Bool MemoryRange__covers ( MemoryRange* mr,
167 const void* startV, SizeT len )
169 vg_assert(len > 0);
170 if (mr->len == 0) {
171 return False;
173 Addr start = (Addr)startV;
174 return start >= mr->start && start + len - 1 <= mr->start + mr->len - 1;
178 /*------------------------------------------------------------*/
179 /*--- (Pass 1 of 3) The EXIDX extractor ---*/
180 /*------------------------------------------------------------*/
182 #define ARM_EXIDX_CANT_UNWIND 0x00000001
183 #define ARM_EXIDX_COMPACT 0x80000000
184 #define ARM_EXTBL_OP_FINISH 0xb0
185 #define ARM_EXIDX_TABLE_LIMIT (255*4)
187 /* These are in the ARM-defined format, so their layout is important. */
188 typedef
189 struct { UInt addr; UInt data; }
190 ExidxEntry;
193 typedef
194 enum {
195 ExSuccess=1, // success
196 ExInBufOverflow, // out-of-range while reading .exidx
197 ExOutBufOverflow, // output buffer is too small
198 ExCantUnwind, // this function is marked CANT_UNWIND
199 ExCantRepresent, // entry valid, but we can't represent it
200 ExInvalid // entry is invalid
202 ExExtractResult;
205 /* Helper function for fishing bits out of the EXIDX representation. */
206 static const void* Prel31ToAddr(const void* addr)
208 UInt offset32 = *(const UInt*)addr;
209 // sign extend offset32[30:0] to 64 bits -- copy bit 30 to positions
210 // 63:31 inclusive.
211 ULong offset64 = offset32;
212 if (offset64 & (1ULL << 30))
213 offset64 |= 0xFFFFFFFF80000000ULL;
214 else
215 offset64 &= 0x000000007FFFFFFFULL;
216 return ((const UChar*)addr) + (UWord)offset64;
220 // Extract unwind bytecode for the function denoted by |entry| into |buf|,
221 // and return the number of bytes of |buf| written, along with a code
222 // indicating the outcome.
223 static
224 ExExtractResult ExtabEntryExtract ( MemoryRange* mr_exidx,
225 MemoryRange* mr_extab,
226 const ExidxEntry* entry,
227 UChar* buf, SizeT buf_size,
228 /*OUT*/SizeT* buf_used)
230 Bool ok;
231 MemoryRange mr_out;
232 ok = MemoryRange__init(&mr_out, buf, buf_size);
233 if (!ok) return ExOutBufOverflow;
235 *buf_used = 0;
237 # define PUT_BUF_U8(_byte) \
238 do { if (!MemoryRange__covers(&mr_out, &buf[*buf_used], 1)) \
239 return ExOutBufOverflow; \
240 buf[(*buf_used)++] = (_byte); } while (0)
242 # define GET_EX_U32(_lval, _addr, _mr) \
243 do { if (!MemoryRange__covers((_mr), (const void*)(_addr), 4)) \
244 return ExInBufOverflow; \
245 (_lval) = *(const UInt*)(_addr); } while (0)
247 # define GET_EXIDX_U32(_lval, _addr) \
248 GET_EX_U32(_lval, _addr, mr_exidx)
250 # define GET_EXTAB_U32(_lval, _addr) \
251 GET_EX_U32(_lval, _addr, mr_extab)
253 UInt data;
254 GET_EXIDX_U32(data, &entry->data);
256 // A function can be marked CANT_UNWIND if (eg) it is known to be
257 // at the bottom of the stack.
258 if (data == ARM_EXIDX_CANT_UNWIND)
259 return ExCantUnwind;
261 UInt pers; // personality number
262 UInt extra; // number of extra data words required
263 UInt extra_allowed; // number of extra data words allowed
264 const UInt* extbl_data; // the handler entry, if not inlined
266 if (data & ARM_EXIDX_COMPACT) {
267 // The handler table entry has been inlined into the index table entry.
268 // In this case it can only be an ARM-defined compact model, since
269 // bit 31 is 1. Only personalities 0, 1 and 2 are defined for the
270 // ARM compact model, but 1 and 2 are "Long format" and may require
271 // extra data words. Hence the allowable personalities here are:
272 // personality 0, in which case 'extra' has no meaning
273 // personality 1, with zero extra words
274 // personality 2, with zero extra words
275 extbl_data = NULL;
276 pers = (data >> 24) & 0x0F;
277 extra = (data >> 16) & 0xFF;
278 extra_allowed = 0;
280 else {
281 // The index table entry is a pointer to the handler entry. Note
282 // that Prel31ToAddr will read the given address, but we already
283 // range-checked above.
284 extbl_data = Prel31ToAddr(&entry->data);
285 GET_EXTAB_U32(data, extbl_data);
286 if (!(data & ARM_EXIDX_COMPACT)) {
287 // This denotes a "generic model" handler. That will involve
288 // executing arbitrary machine code, which is something we
289 // can't represent here; hence reject it.
290 return ExCantRepresent;
292 // So we have a compact model representation. Again, 3 possible
293 // personalities, but this time up to 255 allowable extra words.
294 pers = (data >> 24) & 0x0F;
295 extra = (data >> 16) & 0xFF;
296 extra_allowed = 255;
297 extbl_data++;
300 // Now look at the handler table entry. The first word is |data|
301 // and subsequent words start at |*extbl_data|. The number of
302 // extra words to use is |extra|, provided that the personality
303 // allows extra words. Even if it does, none may be available --
304 // extra_allowed is the maximum number of extra words allowed. */
305 if (pers == 0) {
306 // "Su16" in the documentation -- 3 unwinding insn bytes
307 // |extra| has no meaning here; instead that byte is an unwind-info byte
308 PUT_BUF_U8(data >> 16);
309 PUT_BUF_U8(data >> 8);
310 PUT_BUF_U8(data);
312 else if ((pers == 1 || pers == 2) && extra <= extra_allowed) {
313 // "Lu16" or "Lu32" respectively -- 2 unwinding insn bytes,
314 // and up to 255 extra words.
315 PUT_BUF_U8(data >> 8);
316 PUT_BUF_U8(data);
317 UInt j;
318 for (j = 0; j < extra; j++) {
319 GET_EXTAB_U32(data, extbl_data);
320 extbl_data++;
321 PUT_BUF_U8(data >> 24);
322 PUT_BUF_U8(data >> 16);
323 PUT_BUF_U8(data >> 8);
324 PUT_BUF_U8(data >> 0);
327 else {
328 // The entry is invalid.
329 return ExInvalid;
332 // Make sure the entry is terminated with "FINISH"
333 if (*buf_used > 0 && buf[(*buf_used) - 1] != ARM_EXTBL_OP_FINISH)
334 PUT_BUF_U8(ARM_EXTBL_OP_FINISH);
336 return ExSuccess;
338 # undef GET_EXTAB_U32
339 # undef GET_EXIDX_U32
340 # undef GET_U32
341 # undef PUT_BUF_U8
345 /*------------------------------------------------------------*/
346 /*--- (Pass 2 of 3) The EXIDX decoder ---*/
347 /*------------------------------------------------------------*/
349 /* This (ExtabData) is an intermediate structure, used to carry
350 information from the decoder (pass 2) to the summariser (pass 3).
351 I don't think its layout is important. */
352 typedef
353 enum {
354 ARM_EXIDX_CMD_FINISH=0x100,
355 ARM_EXIDX_CMD_SUB_FROM_VSP,
356 ARM_EXIDX_CMD_ADD_TO_VSP,
357 ARM_EXIDX_CMD_REG_POP,
358 ARM_EXIDX_CMD_REG_TO_SP,
359 ARM_EXIDX_CMD_VFP_POP,
360 ARM_EXIDX_CMD_WREG_POP,
361 ARM_EXIDX_CMD_WCGR_POP,
362 ARM_EXIDX_CMD_RESERVED,
363 ARM_EXIDX_CMD_REFUSED
365 ExtabCmd;
367 static const HChar* showExtabCmd ( ExtabCmd cmd ) {
368 switch (cmd) {
369 case ARM_EXIDX_CMD_FINISH: return "FINISH";
370 case ARM_EXIDX_CMD_SUB_FROM_VSP: return "SUB_FROM_VSP";
371 case ARM_EXIDX_CMD_ADD_TO_VSP: return "ADD_TO_VSP";
372 case ARM_EXIDX_CMD_REG_POP: return "REG_POP";
373 case ARM_EXIDX_CMD_REG_TO_SP: return "REG_TO_SP";
374 case ARM_EXIDX_CMD_VFP_POP: return "VFP_POP";
375 case ARM_EXIDX_CMD_WREG_POP: return "WREG_POP";
376 case ARM_EXIDX_CMD_WCGR_POP: return "WCGR_POP";
377 case ARM_EXIDX_CMD_RESERVED: return "RESERVED";
378 case ARM_EXIDX_CMD_REFUSED: return "REFUSED";
379 default: return "???";
384 typedef
385 struct { ExtabCmd cmd; UInt data; }
386 ExtabData;
388 static void ppExtabData ( const ExtabData* etd ) {
389 VG_(printf)("ExtabData{%-12s 0x%08x}", showExtabCmd(etd->cmd), etd->data);
393 enum extab_cmd_flags {
394 ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
395 ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
399 /* Forwards */
400 typedef struct _SummState SummState;
401 static Int TranslateCmd(/*MOD*/SummState* state, const ExtabData* edata);
404 // Take the unwind information extracted by ExtabEntryExtract
405 // and parse it into frame-unwind instructions. These are as
406 // specified in "Table 4, ARM-defined frame-unwinding instructions"
407 // in the specification document detailed in comments at the top
408 // of this file.
410 // This reads from |buf[0, +data_size)|. It checks for overruns of
411 // the input buffer and returns a negative value if that happens, or
412 // for any other failure cases. It returns zero in case of success.
413 // Whilst reading the input, it dumps the result in |*state|.
414 static
415 Int ExtabEntryDecode(/*OUT*/SummState* state, const UChar* buf, SizeT buf_size)
417 if (buf == NULL || buf_size == 0)
418 return -3;
420 MemoryRange mr_in;
421 Bool ok = MemoryRange__init(&mr_in, buf, buf_size);
422 if (!ok)
423 return -2;
425 # define GET_BUF_U8(_lval) \
426 do { if (!MemoryRange__covers(&mr_in, buf, 1)) \
427 return -4; \
428 (_lval) = *(buf++); } while (0)
430 const UChar* end = buf + buf_size;
432 while (buf < end) {
433 ExtabData edata;
434 VG_(bzero_inline)(&edata, sizeof(edata));
436 UChar op;
437 GET_BUF_U8(op);
438 if ((op & 0xc0) == 0x00) {
439 // vsp = vsp + (xxxxxx << 2) + 4
440 edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
441 edata.data = (((Int)op & 0x3f) << 2) + 4;
443 else if ((op & 0xc0) == 0x40) {
444 // vsp = vsp - (xxxxxx << 2) - 4
445 edata.cmd = ARM_EXIDX_CMD_SUB_FROM_VSP;
446 edata.data = (((Int)op & 0x3f) << 2) + 4;
448 else if ((op & 0xf0) == 0x80) {
449 UChar op2;
450 GET_BUF_U8(op2);
451 if (op == 0x80 && op2 == 0x00) {
452 // Refuse to unwind
453 edata.cmd = ARM_EXIDX_CMD_REFUSED;
454 } else {
455 // Pop up to 12 integer registers under masks {r15-r12},{r11-r4}
456 edata.cmd = ARM_EXIDX_CMD_REG_POP;
457 edata.data = ((op & 0xf) << 8) | op2;
458 edata.data = edata.data << 4;
461 else if ((op & 0xf0) == 0x90) {
462 if (op == 0x9d || op == 0x9f) {
463 // 9d: Reserved as prefix for ARM register to register moves
464 // 9f: Reserved as prefix for Intel Wireless MMX reg to reg moves
465 edata.cmd = ARM_EXIDX_CMD_RESERVED;
466 } else {
467 // Set vsp = r[nnnn]
468 edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
469 edata.data = op & 0x0f;
472 else if ((op & 0xf0) == 0xa0) {
473 // Pop r4 to r[4+nnn], or
474 // Pop r4 to r[4+nnn] and r14
475 Int nnn = (op & 0x07);
476 edata.data = (1 << (nnn + 1)) - 1;
477 edata.data = edata.data << 4;
478 if (op & 0x08) edata.data |= 1 << 14;
479 edata.cmd = ARM_EXIDX_CMD_REG_POP;
481 else if (op == ARM_EXTBL_OP_FINISH) {
482 // Finish
483 edata.cmd = ARM_EXIDX_CMD_FINISH;
484 buf = end;
486 else if (op == 0xb1) {
487 UChar op2;
488 GET_BUF_U8(op2);
489 if (op2 == 0 || (op2 & 0xf0)) {
490 // Spare
491 edata.cmd = ARM_EXIDX_CMD_RESERVED;
492 } else {
493 // Pop integer registers under mask {r3,r2,r1,r0}
494 edata.cmd = ARM_EXIDX_CMD_REG_POP;
495 edata.data = op2 & 0x0f;
498 else if (op == 0xb2) {
499 // vsp = vsp + 0x204 + (uleb128 << 2)
500 ULong offset = 0;
501 UChar byte, shift = 0;
502 do {
503 GET_BUF_U8(byte);
504 offset |= (byte & 0x7f) << shift;
505 shift += 7;
506 } while ((byte & 0x80) && buf < end);
507 edata.data = offset * 4 + 0x204;
508 edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
510 else if (op == 0xb3 || op == 0xc8 || op == 0xc9) {
511 // b3: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDX-ishly
512 // c8: Pop VFP regs D[16+ssss] to D[16+ssss+cccc], FSTMFDD-ishly
513 // c9: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDD-ishly
514 edata.cmd = ARM_EXIDX_CMD_VFP_POP;
515 GET_BUF_U8(edata.data);
516 if (op == 0xc8) edata.data |= ARM_EXIDX_VFP_SHIFT_16;
517 if (op != 0xb3) edata.data |= ARM_EXIDX_VFP_FSTMD;
519 else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) {
520 // b8: Pop VFP regs D[8] to D[8+nnn], FSTMFDX-ishly
521 // d0: Pop VFP regs D[8] to D[8+nnn], FSTMFDD-ishly
522 edata.cmd = ARM_EXIDX_CMD_VFP_POP;
523 edata.data = 0x80 | (op & 0x07);
524 if ((op & 0xf8) == 0xd0) edata.data |= ARM_EXIDX_VFP_FSTMD;
526 else if (op >= 0xc0 && op <= 0xc5) {
527 // Intel Wireless MMX pop wR[10]-wr[10+nnn], nnn != 6,7
528 edata.cmd = ARM_EXIDX_CMD_WREG_POP;
529 edata.data = 0xa0 | (op & 0x07);
531 else if (op == 0xc6) {
532 // Intel Wireless MMX pop wR[ssss] to wR[ssss+cccc]
533 edata.cmd = ARM_EXIDX_CMD_WREG_POP;
534 GET_BUF_U8(edata.data);
536 else if (op == 0xc7) {
537 UChar op2;
538 GET_BUF_U8(op2);
539 if (op2 == 0 || (op2 & 0xf0)) {
540 // Spare
541 edata.cmd = ARM_EXIDX_CMD_RESERVED;
542 } else {
543 // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
544 edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
545 edata.data = op2 & 0x0f;
548 else {
549 // Spare
550 edata.cmd = ARM_EXIDX_CMD_RESERVED;
553 if (0)
554 VG_(printf)(" edata: cmd %08x data %08x\n",
555 (UInt)edata.cmd, edata.data);
557 Int ret = TranslateCmd ( state, &edata );
558 if (ret < 0) return ret;
560 return 0;
562 # undef GET_BUF_U8
566 /*------------------------------------------------------------*/
567 /*--- (Pass 3 of 3) The EXIDX summariser ---*/
568 /*------------------------------------------------------------*/
570 /* In this translation into DiCfSI_m, we're going to have the CFA play
571 the role of the VSP. That means that the VSP can be exactly any of
572 the CFA expressions, viz: {r7,r11,r12,r13) +/- offset.
574 All of this would be a lot simpler if the DiCfSI_m representation
575 was just a bit more expressive and orthogonal. But it isn't.
577 The central difficulty is that, although we can track changes
578 to the offset of VSP (via vsp_off), we can't deal with assignments
579 of an entirely new expression to it, because the existing
580 rules in |cfi| will almost certainly refer to the CFA, and so
581 changing it will make them invalid. Hence, below:
583 * for the case ARM_EXIDX_CMD_REG_TO_SP we simply disallow
584 assignment, and hence give up, if any rule refers to CFA
586 * for the case ARM_EXIDX_CMD_REG_POP, the SP (hence, VSP) is
587 updated by the pop, give up.
589 This is an ugly hack to work around not having a better (LUL-like)
590 expression representation. That said, these restrictions don't
591 appear to be a big problem in practice.
594 struct _SummState {
595 // The DiCfSI_m under construction
596 DiCfSI_m cfi;
597 Int vsp_off;
598 // For generating CFI register expressions, if needed.
599 DebugInfo* di;
603 /* Generate a trivial CfiExpr, for the ARM(32) integer register
604 numbered |gprNo|. First ensure this DebugInfo has a cfsi_expr
605 array in which to park it. Returns -1 if |gprNo| cannot be
606 represented, otherwise returns a value >= 0. */
607 static
608 Int gen_CfiExpr_CfiReg_ARM_GPR ( /*MB_MOD*/DebugInfo* di, UInt gprNo )
610 CfiReg creg = Creg_INVALID;
611 switch (gprNo) {
612 case 13: creg = Creg_ARM_R13; break;
613 case 12: creg = Creg_ARM_R12; break;
614 case 15: creg = Creg_ARM_R15; break;
615 case 14: creg = Creg_ARM_R14; break;
616 case 7: creg = Creg_ARM_R7; break;
617 default: break;
619 if (creg == Creg_INVALID) {
620 return -1;
622 if (!di->cfsi_exprs) {
623 di->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc), "di.gCCAG",
624 ML_(dinfo_free), sizeof(CfiExpr) );
626 Int res = ML_(CfiExpr_CfiReg)( di->cfsi_exprs, creg );
627 vg_assert(res >= 0);
628 return res;
632 /* Given a DiCfSI_m, find the _how/_off pair for the given ARM(32) GPR
633 number inside |cfsi_m|, or return NULL for both if that register
634 number is not represented. */
635 static
636 void maybeFindExprForRegno( /*OUT*/UChar** howPP, /*OUT*/Int** offPP,
637 DiCfSI_m* cfsi_m, Int regNo )
639 switch (regNo) {
640 case 15: *howPP = &cfsi_m->ra_how; *offPP = &cfsi_m->ra_off; return;
641 case 14: *howPP = &cfsi_m->r14_how; *offPP = &cfsi_m->r14_off; return;
642 case 13: *howPP = &cfsi_m->r13_how; *offPP = &cfsi_m->r13_off; return;
643 case 12: *howPP = &cfsi_m->r12_how; *offPP = &cfsi_m->r12_off; return;
644 case 11: *howPP = &cfsi_m->r11_how; *offPP = &cfsi_m->r11_off; return;
645 case 7: *howPP = &cfsi_m->r7_how; *offPP = &cfsi_m->r7_off; return;
646 default: break;
648 *howPP = NULL; *offPP = NULL;
652 /* Set cfi.cfa_{how,off} so as to be a copy of the expression denoted
653 by (how,off), if it is possible to do so. Returns True on
654 success. */
655 static
656 Bool setCFAfromCFIR( /*MOD*/DiCfSI_m* cfi, XArray*/*CfiExpr*/ cfsi_exprs,
657 UChar how, Int off )
659 switch (how) {
660 case CFIR_EXPR:
661 if (!cfsi_exprs) return False;
662 CfiExpr* e = (CfiExpr*)VG_(indexXA)(cfsi_exprs, off);
663 if (e->tag != Cex_CfiReg) return False;
664 if (e->Cex.CfiReg.reg == Creg_ARM_R7) {
665 cfi->cfa_how = CFIC_ARM_R7REL;
666 cfi->cfa_off = 0;
667 return True;
669 ML_(ppCfiExpr)(cfsi_exprs, off);
670 vg_assert(0);
671 default:
672 break;
674 VG_(printf)("setCFAfromCFIR: FAIL: how %d off %d\n", how, off);
675 vg_assert(0);
676 return False;
680 #define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
681 #define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
682 #define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
685 static Bool mentionsCFA ( DiCfSI_m* cfi )
687 # define MENTIONS_CFA(_how) ((_how) == CFIR_CFAREL || (_how) == CFIR_MEMCFAREL)
688 if (MENTIONS_CFA(cfi->ra_how)) return True;
689 if (MENTIONS_CFA(cfi->r14_how)) return True;
690 if (MENTIONS_CFA(cfi->r13_how)) return True;
691 if (MENTIONS_CFA(cfi->r12_how)) return True;
692 if (MENTIONS_CFA(cfi->r11_how)) return True;
693 if (MENTIONS_CFA(cfi->r7_how)) return True;
694 return False;
695 # undef MENTIONS_CFA
699 // Translate command from extab_data to command for Module.
700 static
701 Int TranslateCmd(/*MOD*/SummState* state, const ExtabData* edata)
703 /* Stay sane: check that the CFA has the expected form. */
704 vg_assert(state);
705 switch (state->cfi.cfa_how) {
706 case CFIC_ARM_R13REL: case CFIC_ARM_R12REL:
707 case CFIC_ARM_R11REL: case CFIC_ARM_R7REL: break;
708 default: vg_assert(0);
711 if (0) {
712 VG_(printf)(" TranslateCmd: ");
713 ppExtabData(edata);
714 VG_(printf)("\n");
717 Int ret = 0;
718 switch (edata->cmd) {
719 case ARM_EXIDX_CMD_FINISH:
720 /* Copy LR to PC if there isn't currently a rule for PC in force. */
721 if (state->cfi.ra_how == CFIR_UNKNOWN) {
722 if (state->cfi.r14_how == CFIR_UNKNOWN) {
723 state->cfi.ra_how = CFIR_EXPR;
724 state->cfi.ra_off = gen_CfiExpr_CfiReg_ARM_GPR(state->di, 14);
725 vg_assert(state->cfi.ra_off >= 0);
726 } else {
727 state->cfi.ra_how = state->cfi.r14_how;
728 state->cfi.ra_off = state->cfi.r14_off;
731 break;
732 case ARM_EXIDX_CMD_SUB_FROM_VSP:
733 state->vsp_off -= (Int)(edata->data);
734 break;
735 case ARM_EXIDX_CMD_ADD_TO_VSP:
736 state->vsp_off += (Int)(edata->data);
737 break;
738 case ARM_EXIDX_CMD_REG_POP: {
739 UInt i;
740 for (i = 0; i < 16; i++) {
741 if (edata->data & (1 << i)) {
742 // See if we're summarising for int register |i|. If so,
743 // describe how to pull it off the stack. The cast of |i| is
744 // a bit of a kludge but works because DW_REG_ARM_Rn has the
745 // value |n|, for 0 <= |n| <= 15 -- that is, for the ARM
746 // general-purpose registers.
747 UChar* rX_howP = NULL;
748 Int* rX_offP = NULL;
749 maybeFindExprForRegno(&rX_howP, &rX_offP, &state->cfi, i);
750 if (rX_howP) {
751 vg_assert(rX_offP);
752 /* rX_howP and rX_offP point at one of the rX fields
753 in |state->cfi|. Hence the following assignments
754 are really updating |state->cfi|. */
755 *rX_howP = CFIR_MEMCFAREL;
756 *rX_offP = state->vsp_off;
757 } else {
758 /* We're not tracking this register, so ignore it. */
759 vg_assert(!rX_offP);
761 state->vsp_off += 4;
764 /* Set cfa in case the SP got popped. */
765 if (edata->data & (1 << 13)) {
766 // vsp = curr_rules_.mR13expr;
767 //state->cfi.cfa_how =
768 //state->cfi.cfa_off =
769 //state->vsp_off = 0;
770 // If this happens, it would make the existing CFA references
771 // in the summary invalid. So give up instead.
772 goto cant_summarise;
774 break;
776 case ARM_EXIDX_CMD_REG_TO_SP: {
777 /* We're generating a new value for the CFA/VSP here. Hence,
778 if the summary already refers to the CFA at all, we can't
779 go any further, and have to abandon summarisation. */
780 if (mentionsCFA(&state->cfi))
781 goto cant_summarise;
782 vg_assert(edata->data < 16);
783 Int reg_no = edata->data;
784 // Same comment as above, re the casting of |reg_no|, applies.
785 UChar* rX_howP = NULL;
786 Int* rX_offP = NULL;
787 maybeFindExprForRegno(&rX_howP, &rX_offP, &state->cfi, reg_no);
788 if (rX_howP) {
789 vg_assert(rX_offP);
790 if (*rX_howP == CFIR_UNKNOWN) {
791 //curr_rules_.mR13expr = LExpr(LExpr::NODEREF, reg_no, 0);
792 Int expr_ix = gen_CfiExpr_CfiReg_ARM_GPR(state->di, reg_no);
793 if (expr_ix >= 0) {
794 state->cfi.r13_how = CFIR_EXPR;
795 state->cfi.r13_off = expr_ix;
796 } else {
797 goto cant_summarise;
799 } else {
800 //curr_rules_.mR13expr = *reg_exprP;
801 state->cfi.r13_how = *rX_howP;
802 state->cfi.r13_off = *rX_offP;
804 //vsp = curr_rules_.mR13expr;
805 Bool ok = setCFAfromCFIR( &state->cfi, state->di->cfsi_exprs,
806 state->cfi.r13_how, state->cfi.r13_off );
807 if (!ok) goto cant_summarise;
808 state->vsp_off = 0;
809 } else {
810 vg_assert(!rX_offP);
812 break;
814 case ARM_EXIDX_CMD_VFP_POP: {
815 /* Don't recover VFP registers, but be sure to adjust the stack
816 pointer. */
817 UInt i;
818 for (i = ARM_EXBUF_START(edata->data);
819 i <= ARM_EXBUF_END(edata->data); i++) {
820 state->vsp_off += 8;
822 if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
823 state->vsp_off += 4;
825 break;
827 case ARM_EXIDX_CMD_WREG_POP: {
828 UInt i;
829 for (i = ARM_EXBUF_START(edata->data);
830 i <= ARM_EXBUF_END(edata->data); i++) {
831 state->vsp_off += 8;
833 break;
835 case ARM_EXIDX_CMD_WCGR_POP: {
836 UInt i;
837 // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
838 for (i = 0; i < 4; i++) {
839 if (edata->data & (1 << i)) {
840 state->vsp_off += 4;
843 break;
845 case ARM_EXIDX_CMD_REFUSED:
846 case ARM_EXIDX_CMD_RESERVED:
847 ret = -1;
848 break;
850 return ret;
852 cant_summarise:
853 return -10;
857 /* Initialise the EXIDX summariser, by writing initial values in |state|. */
858 static
859 void AddStackFrame ( /*OUT*/SummState* state,
860 DebugInfo* di )
862 VG_(bzero_inline)(state, sizeof(*state));
863 state->vsp_off = 0;
864 state->di = di;
865 /* Initialise the DiCfSI_m that we are building. */
866 state->cfi.cfa_how = CFIC_ARM_R13REL;
867 state->cfi.cfa_off = 0;
868 state->cfi.ra_how = CFIR_UNKNOWN;
869 state->cfi.r14_how = CFIR_UNKNOWN;
870 state->cfi.r13_how = CFIR_UNKNOWN;
871 state->cfi.r12_how = CFIR_UNKNOWN;
872 state->cfi.r11_how = CFIR_UNKNOWN;
873 state->cfi.r7_how = CFIR_UNKNOWN;
876 static
877 void SubmitStackFrame( /*MOD*/DebugInfo* di,
878 SummState* state, Addr avma, SizeT len )
880 // JRS: I'm really not sure what this means, or if it is necessary
881 // return address always winds up in pc
882 //stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra"
883 // = stack_frame_entry_->initial_rules[ustr__pc()];
884 // maybe don't need to do anything here?
886 // the final value of vsp is the new value of sp.
887 switch (state->cfi.cfa_how) {
888 case CFIC_ARM_R13REL: case CFIC_ARM_R12REL:
889 case CFIC_ARM_R11REL: case CFIC_ARM_R7REL: break;
890 default: vg_assert(0);
892 state->cfi.r13_how = CFIR_CFAREL;
893 state->cfi.r13_off = state->vsp_off;
895 // Finally, add the completed RuleSet to the SecMap
896 if (len > 0) {
898 // Futz with the rules for r4 .. r11 in the same way as happens
899 // with the CFI summariser:
900 /* Mark callee-saved registers (r4 .. r11) as unchanged, if there is
901 no other information about them. FIXME: do this just once, at
902 the point where the ruleset is committed. */
903 if (state->cfi.r7_how == CFIR_UNKNOWN) {
904 state->cfi.r7_how = CFIR_SAME;
905 state->cfi.r7_off = 0;
907 if (state->cfi.r11_how == CFIR_UNKNOWN) {
908 state->cfi.r11_how = CFIR_SAME;
909 state->cfi.r11_off = 0;
911 if (state->cfi.r12_how == CFIR_UNKNOWN) {
912 state->cfi.r12_how = CFIR_SAME;
913 state->cfi.r12_off = 0;
915 if (state->cfi.r14_how == CFIR_UNKNOWN) {
916 state->cfi.r14_how = CFIR_SAME;
917 state->cfi.r14_off = 0;
920 // And add them
921 ML_(addDiCfSI)(di, avma, len, &state->cfi);
922 if (di->trace_cfi)
923 ML_(ppDiCfSI)(di->cfsi_exprs, avma, len, &state->cfi);
928 /*------------------------------------------------------------*/
929 /*--- Top level ---*/
930 /*------------------------------------------------------------*/
932 void ML_(read_exidx) ( /*MOD*/DebugInfo* di,
933 UChar* exidx_img, SizeT exidx_size,
934 UChar* extab_img, SizeT extab_size,
935 Addr text_last_svma,
936 PtrdiffT text_bias )
938 if (di->trace_cfi)
939 VG_(printf)("BEGIN ML_(read_exidx) exidx_img=[%p, +%lu) "
940 "extab_img=[%p, +%lu) text_last_svma=%lx text_bias=%lx\n",
941 exidx_img, exidx_size, extab_img, extab_size,
942 text_last_svma, (UWord)text_bias);
943 Bool ok;
944 MemoryRange mr_exidx, mr_extab;
945 ok = MemoryRange__init(&mr_exidx, exidx_img, exidx_size);
946 ok = ok && MemoryRange__init(&mr_extab, extab_img, extab_size);
947 if (!ok) {
948 complain(".exidx or .extab image area wraparound");
949 return;
952 const ExidxEntry* start_img = (const ExidxEntry*)exidx_img;
953 const ExidxEntry* end_img = (const ExidxEntry*)(exidx_img + exidx_size);
955 if (VG_(clo_verbosity) > 1)
956 VG_(message)(Vg_DebugMsg, " Reading EXIDX entries: %lu available\n",
957 exidx_size / sizeof(ExidxEntry) );
959 // Iterate over each of the EXIDX entries (pairs of 32-bit words).
960 // These occupy the entire .exidx section.
961 UWord n_attempted = 0, n_successful = 0;
963 const ExidxEntry* entry_img;
964 for (entry_img = start_img; entry_img < end_img; ++entry_img) {
966 n_attempted++;
967 // Figure out the code address range that this table entry_img is
968 // associated with.
969 Addr avma = (Addr)Prel31ToAddr(&entry_img->addr);
970 if (di->trace_cfi)
971 VG_(printf)("XXX1 entry: entry->addr 0x%x, avma 0x%lx\n",
972 entry_img->addr, avma);
974 Addr next_avma;
975 if (entry_img < end_img - 1) {
976 next_avma = (Addr)Prel31ToAddr(&(entry_img+1)->addr);
977 } else {
978 // This is the last EXIDX entry in the sequence, so we don't
979 // have an address for the start of the next function, to limit
980 // this one. Instead use the address of the last byte of the
981 // text section associated with this .exidx section, that we
982 // have been given. So as to avoid junking up the CFI unwind
983 // tables with absurdly large address ranges in the case where
984 // text_last_svma_ is wrong, only use the value if it is nonzero
985 // and within one page of |svma|. Otherwise assume a length of 1.
987 // In some cases, gcc has been observed to finish the exidx
988 // section with an entry of length 1 marked CANT_UNWIND,
989 // presumably exactly for the purpose of giving a definite
990 // length for the last real entry, without having to look at
991 // text segment boundaries.
992 Addr text_last_avma = text_last_svma + text_bias;
994 Bool plausible;
995 Addr maybe_next_avma = text_last_avma + 1;
996 if (maybe_next_avma > avma && maybe_next_avma - avma <= 4096) {
997 next_avma = maybe_next_avma;
998 plausible = True;
999 } else {
1000 next_avma = avma + 1;
1001 plausible = False;
1004 if (!plausible && avma != text_last_avma + 1) {
1005 HChar buf[100];
1006 VG_(snprintf)(buf, sizeof(buf),
1007 "Implausible EXIDX last entry size %lu"
1008 "; using 1 instead.", text_last_avma - avma);
1009 buf[sizeof(buf)-1] = 0;
1010 complain(buf);
1014 // Extract the unwind info into |buf|. This might fail for
1015 // various reasons. It involves reading both the .exidx and
1016 // .extab sections. All accesses to those sections are
1017 // bounds-checked.
1018 if (di->trace_cfi)
1019 VG_(printf)("XXX1 entry is for AVMA 0x%lx 0x%lx\n",
1020 avma, next_avma-1);
1021 UChar buf[ARM_EXIDX_TABLE_LIMIT];
1022 SizeT buf_used = 0;
1023 ExExtractResult res
1024 = ExtabEntryExtract(&mr_exidx, &mr_extab,
1025 entry_img, buf, sizeof(buf), &buf_used);
1026 if (res != ExSuccess) {
1027 // Couldn't extract the unwind info, for some reason. Move on.
1028 switch (res) {
1029 case ExInBufOverflow:
1030 complain("ExtabEntryExtract: .exidx/.extab section overrun");
1031 break;
1032 case ExOutBufOverflow:
1033 complain("ExtabEntryExtract: bytecode buffer overflow");
1034 break;
1035 case ExCantUnwind:
1036 // Some functions are marked CantUnwind by the compiler.
1037 // Don't record these as attempted, since that's just
1038 // confusing, and failure to summarise them is not the fault
1039 // of this code.
1040 n_attempted--;
1041 if (0)
1042 complain("ExtabEntryExtract: function is marked CANT_UNWIND");
1043 break;
1044 case ExCantRepresent:
1045 complain("ExtabEntryExtract: bytecode can't be represented");
1046 break;
1047 case ExInvalid:
1048 complain("ExtabEntryExtract: index table entry is invalid");
1049 break;
1050 default: {
1051 HChar mbuf[100];
1052 VG_(snprintf)(mbuf, sizeof(mbuf),
1053 "ExtabEntryExtract: unknown error: %d", (Int)res);
1054 buf[sizeof(mbuf)-1] = 0;
1055 complain(mbuf);
1056 break;
1059 continue;
1062 // Finally, work through the unwind instructions in |buf| and
1063 // create CFI entries that Valgrind can use. This can also fail.
1064 // First, initialise the summariser's running state, into which
1065 // ExtabEntryDecode will write the CFI entries.
1067 SummState state;
1068 AddStackFrame( &state, di );
1069 Int ret = ExtabEntryDecode( &state, buf, buf_used );
1070 if (ret < 0) {
1071 /* Failed summarisation. Ignore and move on. */
1072 HChar mbuf[100];
1073 VG_(snprintf)(mbuf, sizeof(mbuf),
1074 "ExtabEntryDecode: failed with error code: %d", ret);
1075 mbuf[sizeof(mbuf)-1] = 0;
1076 complain(mbuf);
1077 } else {
1078 /* Successful summarisation. Add it to the collection. */
1079 SubmitStackFrame( di, &state, avma, next_avma - avma );
1080 n_successful++;
1083 } /* iterating over .exidx */
1085 if (VG_(clo_verbosity) > 1)
1086 VG_(message)(Vg_DebugMsg,
1087 " Reading EXIDX entries: %lu attempted, %lu successful\n",
1088 n_attempted, n_successful);
1091 #endif /* defined(VGA_arm) */
1093 /*--------------------------------------------------------------------*/
1094 /*--- end readexidx.c ---*/
1095 /*--------------------------------------------------------------------*/