2 * Copyright (c) 1996-2011 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as "Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * By your use of Paradyn, you understand and agree that we (or any
12 * other person or entity with proprietary rights in Paradyn) are
13 * under no obligation to provide either maintenance services,
14 * update services, notices of latent defects, or correction of
15 * defects for Paradyn.
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License, or (at your option) any later version.
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #if !defined(DWARF_SW_H_)
39 Dwarf_Signed fde_count;
41 Dwarf_Signed cie_count;
46 dwarf_status_uninitialized,
52 dwarf_status_t fde_dwarf_status;
54 std::vector<fde_cie_data> fde_data;
57 DwarfSW(Dwarf_Debug dbg_, unsigned addr_width_);
60 bool hasFrameDebugInfo();
61 bool getRegValueAtFrame(Address pc,
62 Dyninst::MachRegister reg,
63 Dyninst::MachRegisterVal ®_result,
64 Dyninst::Architecture arch,
65 ProcessReader *reader);
68 inline DwarfSW::DwarfSW(Dwarf_Debug dbg_, unsigned addr_width_) :
70 addr_width(addr_width_),
71 fde_dwarf_status(dwarf_status_uninitialized)
75 inline DwarfSW::~DwarfSW()
77 if (fde_dwarf_status != dwarf_status_ok)
79 for (unsigned i=0; i<fde_data.size(); i++)
81 dwarf_fde_cie_list_dealloc(dbg,
82 fde_data[i].cie_data, fde_data[i].cie_count,
83 fde_data[i].fde_data, fde_data[i].fde_count);
87 inline bool DwarfSW::hasFrameDebugInfo()
90 return fde_dwarf_status == dwarf_status_ok;
93 inline bool DwarfSW::getRegValueAtFrame(Address pc,
94 Dyninst::MachRegister reg,
95 Dyninst::MachRegisterVal ®_result,
96 Dyninst::Architecture arch,
97 ProcessReader *reader)
101 Dwarf_Addr lowpc, hipc;
105 * Initialize the FDE and CIE data. This is only really done once,
106 * after which setupFdeData will immediately return.
109 if (!fde_data.size()) {
110 setSymtabError(Bad_Frame_Data);
116 * Get the FDE at this PC. The FDE contains the rules for getting
117 * registers at the given PC in this frame.
121 for (cur_fde=0; cur_fde<fde_data.size(); cur_fde++)
123 result = dwarf_get_fde_at_pc(fde_data[cur_fde].fde_data,
124 (Dwarf_Addr) pc, &fde, &lowpc, &hipc, &err);
125 if (result == DW_DLV_ERROR)
127 setSymtabError(Bad_Frame_Data);
130 else if (result == DW_DLV_OK) {
137 setSymtabError(No_Frame_Entry);
141 Dwarf_Half dwarf_reg;
142 if (reg == Dyninst::ReturnAddr) {
144 * We should be getting the return address for the stack frame.
145 * This is treated as a virtual register in the
146 * FDE. We can look up the virtual register in the CIE.
149 result = dwarf_get_cie_of_fde(fde, &cie, &err);
150 if (result != DW_DLV_OK) {
151 setSymtabError(Bad_Frame_Data);
155 Dwarf_Unsigned bytes_in_cie;
156 result = dwarf_get_cie_info(cie, &bytes_in_cie, NULL, NULL, NULL, NULL,
157 &dwarf_reg, NULL, NULL, &err);
158 if (result != DW_DLV_OK) {
159 setSymtabError(Bad_Frame_Data);
163 else if (reg == Dyninst::FrameBase) {
164 dwarf_reg = DW_FRAME_CFA_COL3;
167 dwarf_reg = DynToDwarfReg(reg);
170 Dwarf_Small value_type;
171 Dwarf_Signed offset_relevant, register_num, offset_or_block_len;
176 * Decode the rule that describes how to get dwarf_reg at pc.
178 if (dwarf_reg != DW_FRAME_CFA_COL3) {
179 result = dwarf_get_fde_info_for_reg3(fde, dwarf_reg, pc, &value_type,
180 &offset_relevant, ®ister_num,
181 &offset_or_block_len,
182 &block_ptr, &row_pc, &err);
185 result = dwarf_get_fde_info_for_cfa_reg3(fde, pc, &value_type,
186 &offset_relevant, ®ister_num,
187 &offset_or_block_len,
188 &block_ptr, &row_pc, &err);
190 if (result == DW_DLV_ERROR) {
191 setSymtabError(Bad_Frame_Data);
196 * Interpret the rule and turn it into a real value.
198 unsigned word_size = addr_width;
200 Dyninst::Address res_addr = 0;
201 Dyninst::MachRegisterVal register_val;
203 if (value_type == DW_EXPR_OFFSET || value_type == DW_EXPR_VAL_OFFSET)
205 if (register_num == DW_FRAME_CFA_COL3) {
206 bool bresult = getRegValueAtFrame(pc, Dyninst::FrameBase,
207 register_val, arch, reader);
211 else if (register_num == DW_FRAME_SAME_VAL) {
212 bool bresult = reader->GetReg(reg, register_val);
214 setSymtabError(Frame_Read_Error);
217 reg_result = register_val;
221 Dyninst::MachRegister dyn_registr = DwarfToDynReg(register_num, arch);
222 bool bresult = reader->GetReg(dyn_registr, register_val);
224 setSymtabError(Frame_Read_Error);
230 if ((value_type == DW_EXPR_VAL_OFFSET) ||
231 (value_type == DW_EXPR_OFFSET && dwarf_reg == DW_FRAME_CFA_COL3)) {
232 assert(offset_relevant);
233 reg_result = (Dyninst::MachRegisterVal) (register_val + offset_or_block_len);
236 else if (value_type == DW_EXPR_OFFSET && offset_relevant) {
237 res_addr = (Dyninst::Address) (register_val + offset_or_block_len);
239 else if (value_type == DW_EXPR_OFFSET && !offset_relevant)
241 reg_result = register_val;
244 else if (value_type == DW_EXPR_VAL_EXPRESSION || value_type == DW_EXPR_EXPRESSION)
246 Dwarf_Locdesc *llbuf = NULL;
247 Dwarf_Signed listlen = 0;
248 result = dwarf_loclist_from_expr(dbg, block_ptr, offset_or_block_len, &llbuf, &listlen, &err);
249 if (result != DW_DLV_OK) {
254 long int end_result = 0;
255 bool bresult = decodeDwarfExpression(llbuf, NULL, NULL, locset, reader,
257 dwarf_dealloc(dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK);
258 dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC);
259 if (bresult && value_type == DW_EXPR_EXPRESSION) {
260 if (word_size == 4) {
262 bresult = reader->ReadMem((Dyninst::Address) end_result, &r, 4);
265 else if (word_size == 8) {
267 bresult = reader->ReadMem((Dyninst::Address) end_result, &r, 8);
271 assert(0); //Unknown word size
274 else if (bresult && value_type == DW_EXPR_VAL_EXPRESSION) {
275 reg_result = end_result;
281 setSymtabError(Bad_Frame_Data);
286 bool bresult = false;
287 if (word_size == 4) {
289 bresult = reader->ReadMem(res_addr, &i, word_size);
290 reg_result = (Dyninst::MachRegisterVal) i;
292 else if (word_size == 8) {
294 bresult = reader->ReadMem(res_addr, &i, word_size);
295 reg_result = (Dyninst::MachRegisterVal) i;
298 setSymtabError(Frame_Read_Error);
305 inline void DwarfSW::setupFdeData()
309 if (fde_dwarf_status == dwarf_status_ok ||
310 fde_dwarf_status == dwarf_status_error)
314 fde_dwarf_status = dwarf_status_error;
318 #if defined(dwarf_has_setframe)
319 dwarf_set_frame_cfa_value(dbg, DW_FRAME_CFA_COL3);
323 int result = dwarf_get_fde_list(dbg,
324 &fc.cie_data, &fc.cie_count,
325 &fc.fde_data, &fc.fde_count,
327 if (result == DW_DLV_OK) {
328 fde_data.push_back(fc);
331 result = dwarf_get_fde_list_eh(dbg,
332 &fc.cie_data, &fc.cie_count,
333 &fc.fde_data, &fc.fde_count,
335 if (result == DW_DLV_OK) {
336 fde_data.push_back(fc);
339 if (!fde_data.size()) {
340 fde_dwarf_status = dwarf_status_error;
343 fde_dwarf_status = dwarf_status_ok;