| /* Interface to prologue value handling for GDB. |
| Copyright (C) 2003-2021 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef PROLOGUE_VALUE_H |
| #define PROLOGUE_VALUE_H |
| |
| /* What sort of value is this? This determines the interpretation |
| of subsequent fields. */ |
| enum prologue_value_kind |
| { |
| /* We don't know anything about the value. This is also used for |
| values we could have kept track of, when doing so would have |
| been too complex and we don't want to bother. The bottom of |
| our lattice. */ |
| pvk_unknown, |
| |
| /* A known constant. K is its value. */ |
| pvk_constant, |
| |
| /* The value that register REG originally had *UPON ENTRY TO THE |
| FUNCTION*, plus K. If K is zero, this means, obviously, just |
| the value REG had upon entry to the function. REG is a GDB |
| register number. Before we start interpreting, we initialize |
| every register R to { pvk_register, R, 0 }. */ |
| pvk_register, |
| }; |
| |
| /* When we analyze a prologue, we're really doing 'abstract |
| interpretation' or 'pseudo-evaluation': running the function's code |
| in simulation, but using conservative approximations of the values |
| it would have when it actually runs. For example, if our function |
| starts with the instruction: |
| |
| addi r1, 42 # add 42 to r1 |
| |
| we don't know exactly what value will be in r1 after executing this |
| instruction, but we do know it'll be 42 greater than its original |
| value. |
| |
| If we then see an instruction like: |
| |
| addi r1, 22 # add 22 to r1 |
| |
| we still don't know what r1's value is, but again, we can say it is |
| now 64 greater than its original value. |
| |
| If the next instruction were: |
| |
| mov r2, r1 # set r2 to r1's value |
| |
| then we can say that r2's value is now the original value of r1 |
| plus 64. |
| |
| It's common for prologues to save registers on the stack, so we'll |
| need to track the values of stack frame slots, as well as the |
| registers. So after an instruction like this: |
| |
| mov (fp+4), r2 |
| |
| then we'd know that the stack slot four bytes above the frame |
| pointer holds the original value of r1 plus 64. |
| |
| And so on. |
| |
| Of course, this can only go so far before it gets unreasonable. If |
| we wanted to be able to say anything about the value of r1 after |
| the instruction: |
| |
| xor r1, r3 # exclusive-or r1 and r3, place result in r1 |
| |
| then things would get pretty complex. But remember, we're just |
| doing a conservative approximation; if exclusive-or instructions |
| aren't relevant to prologues, we can just say r1's value is now |
| 'unknown'. We can ignore things that are too complex, if that loss |
| of information is acceptable for our application. |
| |
| So when I say "conservative approximation" here, what I mean is an |
| approximation that is either accurate, or marked "unknown", but |
| never inaccurate. |
| |
| Once you've reached the current PC, or an instruction that you |
| don't know how to simulate, you stop. Now you can examine the |
| state of the registers and stack slots you've kept track of. |
| |
| - To see how large your stack frame is, just check the value of the |
| stack pointer register; if it's the original value of the SP |
| minus a constant, then that constant is the stack frame's size. |
| If the SP's value has been marked as 'unknown', then that means |
| the prologue has done something too complex for us to track, and |
| we don't know the frame size. |
| |
| - To see where we've saved the previous frame's registers, we just |
| search the values we've tracked --- stack slots, usually, but |
| registers, too, if you want --- for something equal to the |
| register's original value. If the ABI suggests a standard place |
| to save a given register, then we can check there first, but |
| really, anything that will get us back the original value will |
| probably work. |
| |
| Sure, this takes some work. But prologue analyzers aren't |
| quick-and-simple pattern patching to recognize a few fixed prologue |
| forms any more; they're big, hairy functions. Along with inferior |
| function calls, prologue analysis accounts for a substantial |
| portion of the time needed to stabilize a GDB port. So I think |
| it's worthwhile to look for an approach that will be easier to |
| understand and maintain. In the approach used here: |
| |
| - It's easier to see that the analyzer is correct: you just see |
| whether the analyzer properly (albeit conservatively) simulates |
| the effect of each instruction. |
| |
| - It's easier to extend the analyzer: you can add support for new |
| instructions, and know that you haven't broken anything that |
| wasn't already broken before. |
| |
| - It's orthogonal: to gather new information, you don't need to |
| complicate the code for each instruction. As long as your domain |
| of conservative values is already detailed enough to tell you |
| what you need, then all the existing instruction simulations are |
| already gathering the right data for you. |
| |
| A 'struct prologue_value' is a conservative approximation of the |
| real value the register or stack slot will have. */ |
| |
| struct prologue_value { |
| |
| /* What sort of value is this? This determines the interpretation |
| of subsequent fields. */ |
| enum prologue_value_kind kind; |
| |
| /* The meanings of the following fields depend on 'kind'; see the |
| comments for the specific 'kind' values. */ |
| int reg; |
| CORE_ADDR k; |
| }; |
| |
| typedef struct prologue_value pv_t; |
| |
| |
| /* Return the unknown prologue value --- { pvk_unknown, ?, ? }. */ |
| pv_t pv_unknown (void); |
| |
| /* Return the prologue value representing the constant K. */ |
| pv_t pv_constant (CORE_ADDR k); |
| |
| /* Return the prologue value representing the original value of |
| register REG, plus the constant K. */ |
| pv_t pv_register (int reg, CORE_ADDR k); |
| |
| |
| /* Return conservative approximations of the results of the following |
| operations. */ |
| pv_t pv_add (pv_t a, pv_t b); /* a + b */ |
| pv_t pv_add_constant (pv_t v, CORE_ADDR k); /* a + k */ |
| pv_t pv_subtract (pv_t a, pv_t b); /* a - b */ |
| pv_t pv_logical_and (pv_t a, pv_t b); /* a & b */ |
| |
| |
| /* Return non-zero iff A and B are identical expressions. |
| |
| This is not the same as asking if the two values are equal; the |
| result of such a comparison would have to be a pv_boolean, and |
| asking whether two 'unknown' values were equal would give you |
| pv_maybe. Same for comparing, say, { pvk_register, R1, 0 } and { |
| pvk_register, R2, 0}. |
| |
| Instead, this function asks whether the two representations are the |
| same. */ |
| int pv_is_identical (pv_t a, pv_t b); |
| |
| |
| /* Return non-zero if A is known to be a constant. */ |
| int pv_is_constant (pv_t a); |
| |
| /* Return non-zero if A is the original value of register number R |
| plus some constant, zero otherwise. */ |
| int pv_is_register (pv_t a, int r); |
| |
| |
| /* Return non-zero if A is the original value of register R plus the |
| constant K. */ |
| int pv_is_register_k (pv_t a, int r, CORE_ADDR k); |
| |
| /* A conservative boolean type, including "maybe", when we can't |
| figure out whether something is true or not. */ |
| enum pv_boolean { |
| pv_maybe, |
| pv_definite_yes, |
| pv_definite_no, |
| }; |
| |
| |
| /* Decide whether a reference to SIZE bytes at ADDR refers exactly to |
| an element of an array. The array starts at ARRAY_ADDR, and has |
| ARRAY_LEN values of ELT_SIZE bytes each. If ADDR definitely does |
| refer to an array element, set *I to the index of the referenced |
| element in the array, and return pv_definite_yes. If it definitely |
| doesn't, return pv_definite_no. If we can't tell, return pv_maybe. |
| |
| If the reference does touch the array, but doesn't fall exactly on |
| an element boundary, or doesn't refer to the whole element, return |
| pv_maybe. */ |
| enum pv_boolean pv_is_array_ref (pv_t addr, CORE_ADDR size, |
| pv_t array_addr, CORE_ADDR array_len, |
| CORE_ADDR elt_size, |
| int *i); |
| |
| |
| /* A 'pv_area' keeps track of values stored in a particular region of |
| memory. */ |
| class pv_area |
| { |
| public: |
| |
| /* Create a new area, tracking stores relative to the original value |
| of BASE_REG. If BASE_REG is SP, then this effectively records the |
| contents of the stack frame: the original value of the SP is the |
| frame's CFA, or some constant offset from it. |
| |
| Stores to constant addresses, unknown addresses, or to addresses |
| relative to registers other than BASE_REG will trash this area; see |
| pv_area::store_would_trash. |
| |
| To check whether a pointer refers to this area, only the low |
| ADDR_BIT bits will be compared. */ |
| pv_area (int base_reg, int addr_bit); |
| |
| ~pv_area (); |
| |
| DISABLE_COPY_AND_ASSIGN (pv_area); |
| |
| /* Store the SIZE-byte value VALUE at ADDR in AREA. |
| |
| If ADDR is not relative to the same base register we used in |
| creating AREA, then we can't tell which values here the stored |
| value might overlap, and we'll have to mark everything as |
| unknown. */ |
| void store (pv_t addr, |
| CORE_ADDR size, |
| pv_t value); |
| |
| /* Return the SIZE-byte value at ADDR in AREA. This may return |
| pv_unknown (). */ |
| pv_t fetch (pv_t addr, CORE_ADDR size); |
| |
| /* Return true if storing to address ADDR in AREA would force us to |
| mark the contents of the entire area as unknown. This could happen |
| if, say, ADDR is unknown, since we could be storing anywhere. Or, |
| it could happen if ADDR is relative to a different register than |
| the other stores base register, since we don't know the relative |
| values of the two registers. |
| |
| If you've reached such a store, it may be better to simply stop the |
| prologue analysis, and return the information you've gathered, |
| instead of losing all that information, most of which is probably |
| okay. */ |
| bool store_would_trash (pv_t addr); |
| |
| /* Search AREA for the original value of REGISTER. If we can't find |
| it, return zero; if we can find it, return a non-zero value, and if |
| OFFSET_P is non-zero, set *OFFSET_P to the register's offset within |
| AREA. GDBARCH is the architecture of which REGISTER is a member. |
| |
| In the worst case, this takes time proportional to the number of |
| items stored in AREA. If you plan to gather a lot of information |
| about registers saved in AREA, consider calling pv_area::scan |
| instead, and collecting all your information in one pass. */ |
| bool find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p); |
| |
| |
| /* For every part of AREA whose value we know, apply FUNC to CLOSURE, |
| the value's address, its size, and the value itself. */ |
| void scan (void (*func) (void *closure, |
| pv_t addr, |
| CORE_ADDR size, |
| pv_t value), |
| void *closure); |
| |
| private: |
| |
| struct area_entry; |
| |
| /* Delete all entries from AREA. */ |
| void clear_entries (); |
| |
| /* Return a pointer to the first entry we hit in AREA starting at |
| OFFSET and going forward. |
| |
| This may return zero, if AREA has no entries. |
| |
| And since the entries are a ring, this may return an entry that |
| entirely precedes OFFSET. This is the correct behavior: depending |
| on the sizes involved, we could still overlap such an area, with |
| wrap-around. */ |
| struct area_entry *find_entry (CORE_ADDR offset); |
| |
| /* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY; |
| return zero otherwise. AREA is the area to which ENTRY belongs. */ |
| int overlaps (struct area_entry *entry, |
| CORE_ADDR offset, |
| CORE_ADDR size); |
| |
| /* This area's base register. */ |
| int m_base_reg; |
| |
| /* The mask to apply to addresses, to make the wrap-around happen at |
| the right place. */ |
| CORE_ADDR m_addr_mask; |
| |
| /* An element of the doubly-linked ring of entries, or zero if we |
| have none. */ |
| struct area_entry *m_entry; |
| }; |
| |
| #endif /* PROLOGUE_VALUE_H */ |