|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2009-2011 David Anderson. All Rights Reserved.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is free software; you can redistribute it and/or modify it
|
|
Packit |
cdaae3 |
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
Packit |
cdaae3 |
as published by the Free Software Foundation.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is distributed in the hope that it would be useful, but
|
|
Packit |
cdaae3 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
cdaae3 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Further, this software is distributed without any warranty that it is
|
|
Packit |
cdaae3 |
free of the rightful claim of any third person regarding infringement
|
|
Packit |
cdaae3 |
or the like. Any license provided herein, whether implied or
|
|
Packit |
cdaae3 |
otherwise, applies only to this software file. Patent licenses, if
|
|
Packit |
cdaae3 |
any, provided herein do not apply to combinations of this program with
|
|
Packit |
cdaae3 |
other software, or any other product whatsoever.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
cdaae3 |
License along with this program; if not, write the Free Software
|
|
Packit |
cdaae3 |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
Packit |
cdaae3 |
USA.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#include "config.h"
|
|
Packit |
cdaae3 |
#include "dwarf_incl.h"
|
|
Packit |
cdaae3 |
#include <stdio.h>
|
|
Packit |
cdaae3 |
#include <stdlib.h>
|
|
Packit |
cdaae3 |
#include "dwarf_frame.h"
|
|
Packit |
cdaae3 |
#include "dwarf_arange.h" /* using Arange as a way to build a list */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Used by rqs (an IRIX application).
|
|
Packit |
cdaae3 |
Not needed except for that one application.
|
|
Packit |
cdaae3 |
Should be moved to its own source file since
|
|
Packit |
cdaae3 |
it is so rarely needed.
|
|
Packit |
cdaae3 |
Returns DW_DLV_OK if returns the arrays.
|
|
Packit |
cdaae3 |
Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
|
|
Packit |
cdaae3 |
Returns DW_DLV_ERROR if there is an error.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Uses DW_FRAME_CFA_COL because IRIX is only DWARF2
|
|
Packit |
cdaae3 |
and that is what IRIX compilers and compatible
|
|
Packit |
cdaae3 |
compilers support on IRIX.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
|
|
Packit |
cdaae3 |
Dwarf_Off ** offsetlist,
|
|
Packit |
cdaae3 |
Dwarf_Signed * returncount,
|
|
Packit |
cdaae3 |
Dwarf_Error * err)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
int retval = DW_DLV_OK;
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
Dwarf_Cie *cie_data = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed cie_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Fde *fde_data = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed fde_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed i = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned u = 0;
|
|
Packit |
cdaae3 |
Dwarf_Frame_Op *frame_inst = 0;
|
|
Packit |
cdaae3 |
Dwarf_Fde fdep = 0;
|
|
Packit |
cdaae3 |
Dwarf_Cie ciep = 0;
|
|
Packit |
cdaae3 |
Dwarf_Chain curr_chain = 0;
|
|
Packit |
cdaae3 |
Dwarf_Chain head_chain = 0;
|
|
Packit |
cdaae3 |
Dwarf_Chain prev_chain = 0;
|
|
Packit |
cdaae3 |
Dwarf_Arange arange = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned arange_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Addr *arange_addrs = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off *arange_offsets = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_fde_list(dbg, &cie_data, &cie_count,
|
|
Packit |
cdaae3 |
&fde_data, &fde_count, err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = _dwarf_load_section(dbg, &dbg->de_debug_frame, err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_frame.dss_size) {
|
|
Packit |
cdaae3 |
return (DW_DLV_NO_ENTRY);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for (i = 0; i < cie_count; i++) {
|
|
Packit |
cdaae3 |
Dwarf_Off instoff = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed initial_instructions_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small *instr_end = 0;
|
|
Packit |
cdaae3 |
Dwarf_Sword icount = 0;
|
|
Packit |
cdaae3 |
int j = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
ciep = cie_data[i];
|
|
Packit |
cdaae3 |
instoff = ciep->ci_cie_instr_start - dbg->de_debug_frame.dss_data;
|
|
Packit |
cdaae3 |
initial_instructions_length = ciep->ci_length +
|
|
Packit |
cdaae3 |
ciep->ci_length_size + ciep->ci_extension_size -
|
|
Packit |
cdaae3 |
(ciep->ci_cie_instr_start - ciep->ci_cie_start);
|
|
Packit |
cdaae3 |
instr_end = ciep->ci_cie_instr_start +
|
|
Packit |
cdaae3 |
initial_instructions_length;
|
|
Packit |
cdaae3 |
res = _dwarf_exec_frame_instr( /* make_instr */ true,
|
|
Packit |
cdaae3 |
&frame_inst,
|
|
Packit |
cdaae3 |
/* search_pc= */ false,
|
|
Packit |
cdaae3 |
/* search_pc_val= */ 0,
|
|
Packit |
cdaae3 |
/* location */ 0,
|
|
Packit |
cdaae3 |
ciep->ci_cie_instr_start,
|
|
Packit |
cdaae3 |
instr_end,
|
|
Packit |
cdaae3 |
/* Dwarf_frame= */ 0,
|
|
Packit |
cdaae3 |
/* cie= */ 0,
|
|
Packit |
cdaae3 |
dbg,
|
|
Packit |
cdaae3 |
DW_FRAME_CFA_COL,
|
|
Packit |
cdaae3 |
&icount,
|
|
Packit |
cdaae3 |
NULL, NULL,err);
|
|
Packit |
cdaae3 |
if (res == DW_DLV_ERROR) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
} else if (res == DW_DLV_NO_ENTRY) {
|
|
Packit |
cdaae3 |
continue;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for (j = 0; j < icount; ++j) {
|
|
Packit |
cdaae3 |
Dwarf_Frame_Op *finst = frame_inst + j;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (finst->fp_base_op == 0 && finst->fp_extended_op == 1) {
|
|
Packit |
cdaae3 |
/* is DW_CFA_set_loc */
|
|
Packit |
cdaae3 |
Dwarf_Addr add = (Dwarf_Addr) finst->fp_offset;
|
|
Packit |
cdaae3 |
Dwarf_Off off = finst->fp_instr_offset + instoff;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange = (Dwarf_Arange)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange->ar_address = add;
|
|
Packit |
cdaae3 |
arange->ar_info_offset = off;
|
|
Packit |
cdaae3 |
arange_count++;
|
|
Packit |
cdaae3 |
curr_chain = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (curr_chain == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
curr_chain->ch_item = arange;
|
|
Packit |
cdaae3 |
if (head_chain == NULL)
|
|
Packit |
cdaae3 |
head_chain = prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
else {
|
|
Packit |
cdaae3 |
prev_chain->ch_next = curr_chain;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
for (i = 0; i < fde_count; i++) {
|
|
Packit |
cdaae3 |
Dwarf_Small *instr_end = 0;
|
|
Packit |
cdaae3 |
Dwarf_Sword icount = 0;
|
|
Packit |
cdaae3 |
Dwarf_Signed instructions_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off instoff = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off off = 0;
|
|
Packit |
cdaae3 |
Dwarf_Addr addr = 0;
|
|
Packit |
cdaae3 |
int j = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
fdep = fde_data[i];
|
|
Packit |
cdaae3 |
off = fdep->fd_initial_loc_pos - dbg->de_debug_frame.dss_data;
|
|
Packit |
cdaae3 |
addr = fdep->fd_initial_location;
|
|
Packit |
cdaae3 |
arange = (Dwarf_Arange)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange->ar_address = addr;
|
|
Packit |
cdaae3 |
arange->ar_info_offset = off;
|
|
Packit |
cdaae3 |
arange_count++;
|
|
Packit |
cdaae3 |
curr_chain = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (curr_chain == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
curr_chain->ch_item = arange;
|
|
Packit |
cdaae3 |
if (head_chain == NULL)
|
|
Packit |
cdaae3 |
head_chain = prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
else {
|
|
Packit |
cdaae3 |
prev_chain->ch_next = curr_chain;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame.dss_data;
|
|
Packit |
cdaae3 |
instructions_length = fdep->fd_length +
|
|
Packit |
cdaae3 |
fdep->fd_length_size + fdep->fd_extension_size -
|
|
Packit |
cdaae3 |
(fdep->fd_fde_instr_start - fdep->fd_fde_start);
|
|
Packit |
cdaae3 |
instr_end = fdep->fd_fde_instr_start + instructions_length;
|
|
Packit |
cdaae3 |
res = _dwarf_exec_frame_instr( /* make_instr */ true,
|
|
Packit |
cdaae3 |
&frame_inst,
|
|
Packit |
cdaae3 |
/* search_pc= */ false,
|
|
Packit |
cdaae3 |
/* search_pc_val= */ 0,
|
|
Packit |
cdaae3 |
/* location */ 0,
|
|
Packit |
cdaae3 |
fdep->fd_fde_instr_start,
|
|
Packit |
cdaae3 |
instr_end,
|
|
Packit |
cdaae3 |
/* Dwarf_frame= */ 0,
|
|
Packit |
cdaae3 |
/* cie= */ 0,
|
|
Packit |
cdaae3 |
dbg,
|
|
Packit |
cdaae3 |
DW_FRAME_CFA_COL,
|
|
Packit |
cdaae3 |
&icount,
|
|
Packit |
cdaae3 |
NULL,NULL,err);
|
|
Packit |
cdaae3 |
if (res == DW_DLV_ERROR) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
} else if (res == DW_DLV_NO_ENTRY) {
|
|
Packit |
cdaae3 |
continue;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for (j = 0; j < icount; ++j) {
|
|
Packit |
cdaae3 |
Dwarf_Frame_Op *finst2 = frame_inst + j;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (finst2->fp_base_op == 0 && finst2->fp_extended_op == 1) {
|
|
Packit |
cdaae3 |
/* is DW_CFA_set_loc */
|
|
Packit |
cdaae3 |
Dwarf_Addr add = (Dwarf_Addr) finst2->fp_offset;
|
|
Packit |
cdaae3 |
Dwarf_Off off2 = finst2->fp_instr_offset + instoff;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange = (Dwarf_Arange)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange->ar_address = add;
|
|
Packit |
cdaae3 |
arange->ar_info_offset = off2;
|
|
Packit |
cdaae3 |
arange_count++;
|
|
Packit |
cdaae3 |
curr_chain = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (curr_chain == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
curr_chain->ch_item = arange;
|
|
Packit |
cdaae3 |
if (head_chain == NULL)
|
|
Packit |
cdaae3 |
head_chain = prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
else {
|
|
Packit |
cdaae3 |
prev_chain->ch_next = curr_chain;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, frame_inst, DW_DLA_FRAME_BLOCK);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
|
|
Packit |
cdaae3 |
arange_addrs = (Dwarf_Addr *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
|
|
Packit |
cdaae3 |
if (arange_addrs == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange_offsets = (Dwarf_Off *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
|
|
Packit |
cdaae3 |
if (arange_offsets == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain = head_chain;
|
|
Packit |
cdaae3 |
for (u = 0; u < arange_count; u++) {
|
|
Packit |
cdaae3 |
Dwarf_Arange ar = curr_chain->ch_item;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange_addrs[u] = ar->ar_address;
|
|
Packit |
cdaae3 |
arange_offsets[u] = ar->ar_info_offset;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
curr_chain = curr_chain->ch_next;
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*returncount = arange_count;
|
|
Packit |
cdaae3 |
*offsetlist = arange_offsets;
|
|
Packit |
cdaae3 |
*addrlist = arange_addrs;
|
|
Packit |
cdaae3 |
return retval;
|
|
Packit |
cdaae3 |
}
|