dwarf_frame.c revision 49d3bc91e27cd871b950d56c01398fa2f2e12ab4
/*
Copyright (C) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
under the terms of version 2.1 of the GNU Lesser General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it would be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Further, this software is distributed without any warranty that it is
free of the rightful claim of any third person regarding infringement
or the like. Any license provided herein, whether implied or
otherwise, applies only to this software file. Patent licenses, if
any, provided herein do not apply to combinations of this program with
other software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
USA.
Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky,
Mountain View, CA 94043, or:
For further information regarding this notice, see:
*/
#include "config.h"
#include "dwarf_incl.h"
#include <stdio.h>
#include <stdlib.h>
#include "dwarf_frame.h"
#include "dwarf_arange.h" /* using Arange as a way to build a
list */
static int
int use_gnu_cie_calc,
Dwarf_Error * error);
/*
This function is the heart of the debug_frame stuff. Don't even
think of reading this without reading both the Libdwarf and
consumer API carefully first. This function basically executes
frame instructions contained in a Cie or an Fde, but does in a
number of different ways depending on the information sought.
Start_instr_ptr points to the first byte of the frame instruction
stream, and final_instr_ptr to the to the first byte after the
last.
The offsets returned in the frame instructions are factored. That
is they need to be multiplied by either the code_alignment_factor
or the data_alignment_factor, as appropriate to obtain the actual
offset. This makes it possible to expand an instruction stream
without the corresponding Cie. However, when an Fde frame instr
sequence is being expanded there must be a valid Cie with a pointer
to an initial table row.
If successful, returns DW_DLV_OK
And sets returned_count thru the pointer
if make_instr is true.
If make_instr is false returned_count
should NOT be used by the caller (returned_count
is set to 0 thru the pointer by this routine...)
If unsuccessful, returns DW_DLV_ERROR
and sets returned_error to the error code
It does not do a whole lot of input validation being a private
function. Please make sure inputs are valid.
(1) If make_instr is true, it makes a list of pointers to
Dwarf_Frame_Op structures containing the frame instructions
executed. A pointer to this list is returned in ret_frame_instr.
Make_instr is true only when a list of frame instructions is to be
returned. In this case since we are not interested in the contents
of the table, the input Cie can be NULL. This is the only case
where the inpute Cie can be NULL.
(2) If search_pc is true, frame instructions are executed till
either a location is reached that is greater than the search_pc_val
provided, or all instructions are executed. At this point the
last row of the table generated is returned in a structure.
A pointer to this structure is supplied in table.
(3) This function is also used to create the initial table row
defined by a Cie. In this case, the Dwarf_Cie pointer cie, is
NULL. For an FDE, however, cie points to the associated Cie.
*/
static int
instr? */
to
list
of
ptrs
to
fr
instrs
*/
value? */
this pc
value */
of frame
instrs. */
past frame
instrs. */
last row. */
*/
Dwarf_Debug */
int *returned_error)
{
/* Sweeps the frame instructions. */
/* Obvious from the documents. */
and must be at least sizeof
Dwarf_ufixed */
/* This is used to end executing frame instructions. */
/* Becomes true when search_pc is true and loc */
/* is greater than search_pc_val. */
Dwarf_Bool search_over = false;
/* Used by the DW_FRAME_advance_loc instr */
/* to hold the increment in pc value. */
/* Contains the length in bytes of */
/* an leb128 encoded number. */
/* Counts the number of frame instructions executed. */
Dwarf_Word instr_count = 0;
/*
These contain the current fields of the current frame
instruction. */
Dwarf_Small fp_base_op = 0;
/*
Stack_table points to the row (Dwarf_Frame ie) being pushed or
popped by a remember or restore instruction. Top_stack points to
the top of the stack of rows. */
/*
These are used only when make_instr is true. Curr_instr is a
pointer to the current frame instruction executed.
Curr_instr_ptr, head_instr_list, and curr_instr_list are used
to form a chain of Dwarf_Frame_Op structs. Dealloc_instr_ptr
is used to deallocate the structs used to form the chain.
Head_instr_block points to a contiguous list of pointers to the
Dwarf_Frame_Op structs executed. */
/*
These are the alignment_factors taken from the Cie provided.
When no input Cie is provided they are set to 1, because only
factored offsets are required. */
/*
This flag indicates when an actual alignment factor is needed.
So if a frame instruction that computes an offset using an
alignment factor is encountered when this flag is set, an error
is returned because the Cie did not have a valid augmentation. */
Dwarf_Bool need_augmentation = false;
Dwarf_Word i;
/* Initialize first row from associated Cie. Using temp regs
explicity */
struct Dwarf_Reg_Rule_s *t1reg;
struct Dwarf_Reg_Rule_s *t1end;
struct Dwarf_Reg_Rule_s *t2reg;
}
} else { /* initialize with same_value */
}
}
/*
The idea here is that the code_alignment_factor and
data_alignment_factor which are needed for certain instructions
are valid only when the Cie has a proper augmentation string.
So if the augmentation is not right, only Frame instruction can
be read. */
} else
instr_ptr += sizeof(Dwarf_Small);
} else {
fp_extended_op = 0;
}
fp_register = 0;
fp_offset = 0;
switch (opcode) {
case DW_CFA_advance_loc:{
/* base op */
if (need_augmentation) {
return DW_DLV_ERROR;
}
search_over = search_pc &&
/* If gone past pc needed, retain old pc. */
if (!search_over)
break;
}
case DW_CFA_offset:{ /* base op */
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
if (need_augmentation) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_restore:{ /* base op */
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
else if (!make_instr) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_set_loc:{
return DW_DLV_ERROR;
}
/* If gone past pc needed, retain old pc. */
if (!search_over)
break;
}
case DW_CFA_advance_loc1:{
instr_ptr += sizeof(Dwarf_Small);
if (need_augmentation) {
return DW_DLV_ERROR;
}
search_over = search_pc &&
/* If gone past pc needed, retain old pc. */
if (!search_over)
break;
}
case DW_CFA_advance_loc2:{
instr_ptr, sizeof(Dwarf_Half));
instr_ptr += sizeof(Dwarf_Half);
if (need_augmentation) {
return DW_DLV_ERROR;
}
search_over = search_pc &&
/* If gone past pc needed, retain old pc. */
if (!search_over)
break;
}
case DW_CFA_advance_loc4:{
instr_ptr, sizeof(Dwarf_ufixed));
instr_ptr += sizeof(Dwarf_ufixed);
if (need_augmentation) {
return DW_DLV_ERROR;
}
search_over = search_pc &&
/* If gone past pc needed, retain old pc. */
if (!search_over)
break;
}
case DW_CFA_offset_extended:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
if (need_augmentation) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_restore_extended:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
} else {
if (!make_instr) {
return DW_DLV_ERROR;
}
}
break;
}
case DW_CFA_undefined:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_same_value:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_register:{
if (reg_noA > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
if (reg_noB > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_remember_state:{
if (stack_table == NULL) {
return DW_DLV_ERROR;
}
for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
break;
}
case DW_CFA_restore_state:{
return DW_DLV_ERROR;
}
for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
break;
}
case DW_CFA_def_cfa:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return (DW_DLV_ERROR);
}
if (need_augmentation) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_def_cfa_register:{
if (reg_no > DW_FRAME_LAST_REG_NUM) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_def_cfa_offset:{
if (need_augmentation) {
return DW_DLV_ERROR;
}
break;
}
case DW_CFA_nop:{
break;
}
#ifdef DW_CFA_GNU_window_save
case DW_CFA_GNU_window_save:{
/* no information: this just tells unwinder to restore
the window registers from the previous frame's
window save area */
break;
}
#endif
#ifdef DW_CFA_GNU_args_size
/* single uleb128 is the current arg area size in bytes. No
register exists yet to save this in */
case DW_CFA_GNU_args_size:{
break;
}
#endif
}
if (make_instr) {
instr_count++;
curr_instr = (Dwarf_Frame_Op *)
if (curr_instr == NULL) {
return DW_DLV_ERROR;
}
if (curr_instr_item == NULL) {
return DW_DLV_ERROR;
}
if (head_instr_chain == NULL)
else {
}
}
}
/*
If frame instruction decoding was right we would stop exactly
at final_instr_ptr. */
if (instr_ptr > final_instr_ptr) {
return DW_DLV_ERROR;
}
/* Create the last row generated. */
}
}
/* Dealloc anything remaining on stack. */
}
if (make_instr) {
/* Allocate list of pointers to Dwarf_Frame_Op's. */
if (head_instr_block == NULL) {
return DW_DLV_ERROR;
}
/*
Store pointers to Dwarf_Frame_Op's in this list and
deallocate the structs that chain the Dwarf_Frame_Op's. */
for (i = 0; i < instr_count; i++) {
*(head_instr_block + i) =
}
} else {
*returned_count = 0;
}
return DW_DLV_OK;
}
static int
{
return -1;
return 1;
}
return 0;
}
/*
* This function expects as input a pointer to Dwarf_Debug (dbg) and a
* a pointer to Cie. It finds the augmentation string and returns after
* setting *augmentation to point to it.
*/
static int
Dwarf_Error * error)
{
size */
int local_length_size;
/*REFERENCED*/ /* Not used in this instance of the macro */
int local_extension_size;
/* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
/* Read the Cie Id field. */
if (cie_id != cie_id_value) {
/* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi
uses -1 in .debug_frame. .eh_frame not quite identical to
.debug_frame */
return (DW_DLV_ERROR);
}
/* Read the version. */
cie_ptr++;
if (version != DW_CIE_VERSION) {
return (DW_DLV_ERROR);
}
/* At this point, cie_ptr is pointing at the augmentation string. */
*augmentation = cie_ptr;
return DW_DLV_OK;
}
int
{
return (DW_DLV_ERROR);
}
return DW_DLV_OK;
}
/*
For g++ .eh_frame fde and cie.
the cie id is different as the
definition of the cie_id in an fde
is the distance back from the address of the
value to the cie.
Or 0 if this is a true cie.
Non standard dwarf, designed this way to be
convenient at run time for an allocated
(mapped into memory as part of the running image) section.
*/
int
Dwarf_Error * error)
{
int res;
res =
error);
return res;
}
res =
/* cie_id_value */ 0,
/* use_gnu_cie_calc= */ 1,
error);
return res;
}
/*
For standard dwarf .debug_frame
cie_id is -1 in a cie, and
is the section offset in the .debug_frame section
of the cie otherwise. Standard dwarf
*/
int
Dwarf_Error * error)
{
int res;
res =
error);
return res;
}
res =
/* use_gnu_cie_calc= */ 0,
error);
return res;
}
static int
{
/* Scans the debug_frame section. */
Dwarf_Small *frame_ptr = 0;
/* Points to the start of the current Fde or Cie. */
Dwarf_Small *start_frame_ptr = 0;
/* Points to the start of the augmented entries of Fde or Cie. */
Dwarf_Small *saved_frame_ptr = 0;
/* Fields for the current Cie being read. */
de_length_size byte dest */
de_length_size byte dest */
Dwarf_Small version = 0;
Dwarf_Small *augmentation = 0;
/*
New_cie points to the Cie being read, and head_cie_ptr and
cur_cie_ptr are used for chaining them up in sequence. */
Dwarf_Word cie_count = 0;
/*
Points to a list of contiguous pointers to Dwarf_Cie
structures. */
/* Fields for the current Fde being read. */
bytes in size */
size */
/*
New_fde points to the current Fde being read, and head_fde_ptr
and cur_fde_ptr are used to chain them up. */
Dwarf_Word fde_count = 0;
/*
Points to a list of contiguous pointers to Dwarf_Fde
structures. */
/*
Is used to check the offset field in the Fde by checking for a
Cie at this address. */
Dwarf_Word i, j;
int res;
if (frame_ptr == 0) {
return DW_DLV_NO_ENTRY;
}
Dwarf_Small *cie_ptr_addr = 0;
int local_extension_size = 0;
int local_length_size = 0;
/* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
if (length % local_length_size != 0) {
return (DW_DLV_ERROR);
}
if (length == 0) {
/* nul bytes at end of section, seen at end of egcs
eh_frame sections (in a.out). Take this as meaning no
section. */
break;
}
ignored. If it is an FDE,
this is the section offset
that allows us to get to the
cie of this fde. Save it for
the fde part of the 'if'
below */
if (cie_id == cie_id_value) {
/* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id.
sgi uses -1 (in .debug_frame). .eh_frame not quite
identical to .debug_frame */
/* this is a CIE, Common Information Entry: See the dwarf
spec, section 6.4.1 */
frame_ptr++;
if (version != DW_CIE_VERSION) {
return (DW_DLV_ERROR);
}
if ((strcmp((char *) augmentation,
DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
return (DW_DLV_ERROR);
}
frame_ptr++;
} else if (augmentation[0] == 'z') {
/* The augmentation starts with a known prefix. See the
dwarf_frame.h for details on the layout. */
return (DW_DLV_ERROR);
}
frame_ptr++;
/* Decode the length of augmented fields. */
/* set the frame_ptr to point at the instruction start.
*/
/*REFERENCED*/ /* Not used in this instance of the macro */
/* this is per egcs-1.1.2 as on RH 6.0 */
return (DW_DLV_ERROR);
}
frame_ptr++;
} else {
/* We do not understand the augmentation string. No
assumption can be made about any fields other than
what we have already read. */
/* FIX -- What are the values of data_alignment_factor,
code_alignement_factor, return_address_register and
instruction start? They were clearly uninitalized in
the previous version and I am leaving them the same
way. */
}
return (DW_DLV_ERROR);
}
cie_count++;
if (head_cie_ptr == NULL)
else {
}
} else {
/* this is an FDE, Frame Description Entry, see the Dwarf
Spec, section 6.4.1 */
/* must be min dwarf_sfixed in size */
/* Get the augmentation string from Cie to identify the
layout of this Fde. */
if (use_gnu_cie_calc) {
/* cie_id value is offset, in section, of the cie_id
itself, to use vm ptr of the value, less the value,
to get to the cie itself. In addition, munge
cie_base_offset to look *as if* it was from real
dwarf. */
} else {
/* Traditional dwarf section offset is in cie_id */
cieptr =
}
if (prev_augmentation_cie_ptr == cieptr &&
prev_augmentation_ptr != NULL) {
} else {
&augmentation, error);
return res;
}
}
if ((strcmp((char *) augmentation,
DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
/* We are pointing at the start of instructions. Do
nothing. */
} else if (augmentation[0] == 'z') {
if (strcmp((char *) augmentation,
DW_CIE_AUGMENTER_STRING_V0) == 0) {
/* The first word is an offset into execption
tables. */
/* ?? THis presumes that the offset is always 32
bits */
sizeof(Dwarf_sfixed));
sizeof(Dwarf_sfixed));
}
/* gnu eh fde case. we do not need to do anything */
/*REFERENCED*/ /* Not used in this instance of the macro */
} else {
/* We do not understand the augmentation string. No
assumption can be made about if the instructions is
present. */
/* FIX -- The old code assumed that the instruction
table starts at the location pointed to by
frame_ptr, clearly incorrect. */
}
return (DW_DLV_ERROR);
}
fde_count++;
if (head_fde_ptr == NULL)
else {
}
}
/* Skip over instructions to start of next frame. */
}
if (cie_count > 0) {
cie_list_ptr = (Dwarf_Cie *)
} else {
return (DW_DLV_NO_ENTRY);
}
if (cie_list_ptr == NULL) {
return (DW_DLV_ERROR);
}
/* Return arguments. */
*cie_data = cie_list_ptr;
for (i = 0; i < cie_count; i++) {
*(cie_list_ptr + i) = cur_cie_ptr;
}
if (fde_count > 0) {
fde_list_ptr = (Dwarf_Fde *)
} else {
return (DW_DLV_NO_ENTRY);
}
if (fde_list_ptr == NULL) {
return (DW_DLV_ERROR);
}
/* Return arguments. */
*fde_data = fde_list_ptr;
last_cie_index = 0;
for (i = 0; i < fde_count; i++) {
*(fde_list_ptr + i) = cur_fde_ptr;
/* we assume that the next fde has the same cie as the ** last
fde and resume the search where we left off */
for (j = last_cie_index; j < cie_count; j++) {
new_cie_index = (Dwarf_Sword) j;
break;
}
}
/* did not find it above, start from 0 and try again */
if (new_cie_index == cie_count) {
for (j = 0; j < last_cie_index; ++j) {
new_cie_index = (Dwarf_Sword) j;
break;
}
}
}
j = new_cie_index;
if (j == cie_count) {
return (DW_DLV_ERROR);
} else {
}
}
/* sort the list by the address, so that dwarf_get_fde_at_pc() can
binary search this list. */
return (DW_DLV_OK);
}
/*
Only works on dwarf sections, not eh_frame
*/
int
{
bytes */
unsigned char *fde_ptr;
unsigned char *cie_ptr;
unsigned char *start_cie_ptr;
/* Fields for the current Cie being read. */
int res;
int resattr;
int sdatares;
int fde_local_extension_size = 0;
int fde_local_length_size = 0;
int cie_local_extension_size = 0;
int cie_local_length_size = 0;
return (DW_DLV_ERROR);
}
return resattr;
}
/* why is this formsdata? FIX */
return sdatares;
}
res =
error);
return res;
}
/* READ_AREA_LENGTH updates fde_ptr for consumed bytes */
if (length % fde_local_length_size != 0) {
return (DW_DLV_ERROR);
}
return res;
}
== 0) ||
/* Do nothing. The fde_ptr is pointing at start of
instructions. */
} else if (augmentation[0] == 'z') {
/* The augmentation starts with a known prefix. See the
dwarf_frame.h for details on the layout. */
0) {
/* The first word is an offset into execption tables. */
sizeof(Dwarf_sfixed));
fde_ptr += sizeof(Dwarf_sfixed);
}
} else {
/* We do not understand the augmentation string. No assumption
can be made about if the instructions is present. */
/* FIX -- The old code assumed that the instruction table
starts at location pointed to by fde_ptr, clearly incorrect.
*/
}
return (DW_DLV_ERROR);
}
/* now read the cie corresponding to the fde */
/* READ_AREA_LENGTH updates cie_ptr for consumed bytes */
if (length % cie_local_length_size != 0) {
return (DW_DLV_ERROR);
}
if (signed_offset == DW_CIE_ID) {
cie_ptr++;
if (version != DW_CIE_VERSION) {
return (DW_DLV_ERROR);
}
if ((strcmp((char *) augmentation,
DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) ||
return (DW_DLV_ERROR);
}
cie_ptr++;
} else if (augmentation[0] == 'z') {
/* The augmentation starts with a known prefix. We can
asssume that the first field is the length of the
augmented fields. */
return (DW_DLV_ERROR);
}
cie_ptr++;
/* Decode the length of augmented fields. */
/* set the cie_ptr to point at the instruction start. */
return (DW_DLV_ERROR);
}
cie_ptr++;
} else {
/* We do not understand the augmentation string. No
assumption can be made about any fields other than what
we have already read. */
/* FIX -- What are the values of data_alignment_factor,
code_alignement_factor, return_address_register and
instruction start? They were clearly uninitalized in
the previous version and I am leaving them the same way.
*/
}
return (DW_DLV_ERROR);
}
} else {
return (DW_DLV_ERROR);
}
return DW_DLV_OK;
}
int
Dwarf_Addr * low_pc,
{
int res;
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
res =
error);
return res;
}
if (func_length != NULL)
if (fde_byte_length != NULL)
if (cie_offset != NULL)
if (fde_offset != NULL)
return DW_DLV_OK;
}
int
Dwarf_Error * error)
{
return (DW_DLV_ERROR);
}
return DW_DLV_OK;
}
int
char **augmenter,
Dwarf_Error * error)
{
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
if (code_alignment_factor != NULL)
if (data_alignment_factor != NULL)
if (return_address_register != NULL)
if (initial_instructions != NULL)
if (initial_instructions_length != NULL) {
}
return (DW_DLV_OK);
}
static int
/* Return the register rules for all registers at a given pc. */
{
Dwarf_Sword i;
int dw_err;
int res;
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
pc_requested >=
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++) {
}
/* ret_frame_instr= */ NULL,
/* search_pc */ false,
/* search_pc_val */ 0,
/* location */ 0,
cie->ci_cie_start)),
if (res == DW_DLV_ERROR) {
return (res);
} else if (res == DW_DLV_NO_ENTRY) {
return res;
}
}
/* ret_frame_instr= */ NULL,
/* search_pc */ true,
/* search_pc_val */ pc_requested,
if (res == DW_DLV_ERROR) {
return (res);
} else if (res == DW_DLV_NO_ENTRY) {
return res;
}
return DW_DLV_OK;
}
int
Dwarf_Addr * row_pc,
Dwarf_Error * error)
{
struct Dwarf_Frame_s fde_table;
Dwarf_Sword i;
int res;
/* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
*/
return res;
}
for (i = 0; i < DW_REG_TABLE_SIZE; i++) {
}
return DW_DLV_OK;
}
int
{
struct Dwarf_Frame_s fde_table;
int res;
if (table_column > DW_FRAME_LAST_REG_NUM) {
return (DW_DLV_ERROR);
}
/* _dwarf_get_fde_info_for_a_pc_row will perform more sanity checks
*/
res =
error);
return res;
}
if (register_num != NULL)
return DW_DLV_OK;
}
/*
Return pointer to the instructions in the dwarf
fde.
*/
int
Dwarf_Error * error)
{
unsigned char *instrs;
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
- instrs;
*outinstraddr = instrs;
*outaddrlen = len;
return DW_DLV_OK;
}
int
{
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
return (DW_DLV_NO_ENTRY);
}
return DW_DLV_OK;
}
/*
Lopc and hipc are extensions to the interface to
return the range of addresses that are described
by the returned fde.
*/
int
Dwarf_Addr * lopc,
{
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
return (DW_DLV_ERROR);
}
{
/* The fde's are sorted by their addresses. Binary search to
find correct fde. */
int low = 0;
int middle = 0;
} else if (pc_of_interest >=
cur_fde->fd_address_range)) {
} else {
break;
}
}
}
if (fde) {
*returned_fde = fde;
return (DW_DLV_OK);
}
return (DW_DLV_NO_ENTRY);
}
int
Dwarf_Error * error)
{
int res;
int dw_err;
if (dbg == 0) {
return (DW_DLV_ERROR);
}
if (returned_op_list == 0 || returned_op_count == 0) {
return (DW_DLV_ERROR);
}
/* The cast to Dwarf_Ptr may get a compiler warning, but it is safe
as it is just an i_length offset from 'instruction' itself. A
caller has made a big mistake if the result is not a valid
pointer. */
/* search_pc */ false,
/* search_pc_val */ 0,
/* location */ 0,
/* Dwarf_Frame */ NULL,
/* cie_ptr */ NULL,
if (res == DW_DLV_ERROR) {
}
return (res);
}
return DW_DLV_OK;
}
/*
Used by rqs. Returns DW_DLV_OK if returns the arrays.
Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
Returns DW_DLV_ERROR if there is an error.
*/
int
Dwarf_Off ** offsetlist,
Dwarf_Error * err)
{
int res;
Dwarf_Signed i;
Dwarf_Chain curr_chain = 0;
Dwarf_Chain head_chain = 0;
Dwarf_Chain prev_chain = 0;
Dwarf_Addr *arange_addrs = 0;
Dwarf_Off *arange_offsets = 0;
return res;
}
res =
err);
return res;
}
for (i = 0; i < cie_count; i++) {
Dwarf_Small *instr_end = 0;
Dwarf_Sword icount = 0;
int j;
int dw_err;
/* search_pc= */ false,
/* search_pc_val= */ 0,
/* location */ 0,
/* Dwarf_frame= */ 0,
/* cie= */ 0,
if (res == DW_DLV_ERROR) {
return (res);
} else if (res == DW_DLV_NO_ENTRY) {
continue;
}
for (j = 0; j < icount; ++j) {
/* is DW_CFA_set_loc */
arange = (Dwarf_Arange)
return (DW_DLV_ERROR);
}
arange_count++;
if (curr_chain == NULL) {
return (DW_DLV_ERROR);
}
if (head_chain == NULL)
else {
}
}
}
}
for (i = 0; i < fde_count; i++) {
Dwarf_Small *instr_end = 0;
Dwarf_Sword icount = 0;
Dwarf_Addr addr = 0;
int j;
int dw_err;
arange = (Dwarf_Arange)
return (DW_DLV_ERROR);
}
arange_count++;
if (curr_chain == NULL) {
return (DW_DLV_ERROR);
}
if (head_chain == NULL)
else {
}
/* search_pc= */ false,
/* search_pc_val= */ 0,
/* location */ 0,
/* Dwarf_frame= */ 0,
/* cie= */ 0,
if (res == DW_DLV_ERROR) {
return (res);
} else if (res == DW_DLV_NO_ENTRY) {
continue;
}
for (j = 0; j < icount; ++j) {
/* is DW_CFA_set_loc */
arange = (Dwarf_Arange)
return (DW_DLV_ERROR);
}
arange_count++;
if (curr_chain == NULL) {
return (DW_DLV_ERROR);
}
if (head_chain == NULL)
else {
}
}
}
}
arange_addrs = (Dwarf_Addr *)
if (arange_addrs == NULL) {
return (DW_DLV_ERROR);
}
arange_offsets = (Dwarf_Off *)
if (arange_offsets == NULL) {
return (DW_DLV_ERROR);
}
for (i = 0; i < arange_count; i++) {
}
*addrlist = arange_addrs;
return retval;
}
/* Used by dwarfdump -v to print offsets, for debugging
dwarf info
*/
/* ARGSUSED 4 */
int
Dwarf_Error * err)
{
int res;
char *start;
char *loc;
res =
err);
return res;
}
return DW_DLV_OK;
}
/* Used by dwarfdump -v to print offsets, for debugging
dwarf info
*/
/* ARGSUSED 4 */
int
{
int res;
char *start;
char *loc;
res =
err);
return res;
}
return DW_DLV_OK;
}