Initial revision

CVS patchset: 6867
CVS date: 2003/05/20 13:51:54
This commit is contained in:
jbj 2003-05-20 13:51:54 +00:00
parent 4ec7ad486e
commit fea55d4139
21 changed files with 1464 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/* Implementation of hash table for DWARF .debug_abbrev section content.
Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define NO_UNDEF
#include "libdwP.h"
#define next_prime __libdwarf_next_prime
extern size_t next_prime (size_t) attribute_hidden;
#include <dynamicsizehash.c>
#undef next_prime
#define next_prime attribute_hidden __libdwarf_next_prime
#include "../lib/next_prime.c"

View File

@ -0,0 +1,24 @@
/* Hash table for DWARF .debug_abbrev section content.
Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifndef _DWARF_ABBREV_HASH_H
#define _DWARF_ABBREV_HASH_H 1
#define NAME Dwarf_Abbrev_Hash
#define TYPE Dwarf_Abbrev *
#define COMPARE(a, b) (0)
#include <dynamicsizehash.h>
#endif /* dwarf_abbrev_hash.h */

View File

@ -0,0 +1,39 @@
/* Return specific DWARF attribute of a DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
Dwarf_Attribute *
dwarf_attr (die, search_name, result)
Dwarf_Die *die;
unsigned int search_name;
Dwarf_Attribute *result;
{
if (die == NULL)
return NULL;
/* Search for the attribute with the given name. */
result->valp = __libdw_find_attr (die, search_name, &result->code,
&result->form);
/* Always fill in the CU information. */
result->cu = die->cu;
return result->code == search_name ? result : NULL;
}

View File

@ -0,0 +1,149 @@
/* Return vhild of current DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libdwP.h"
#include <string.h>
/* Some arbitrary value not conflicting with any existing code. */
#define INVALID 0xffffe444
unsigned char *
internal_function
__libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
unsigned int *codep, unsigned int *formp)
{
Dwarf *dbg = die->cu->dbg;
unsigned char *readp = (unsigned char *) die->addr;
/* First we have to get the abbreviation code so that we can decode
the data in the DIE. */
unsigned int abbrev_code;
get_uleb128 (abbrev_code, readp);
/* Find the abbreviation entry. */
Dwarf_Abbrev *abbrevp = die->abbrev;
if (abbrevp != (Dwarf_Abbrev *) -1l)
{
abbrevp = __libdw_getabbrev (die->cu, abbrev_code);
die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
}
if (unlikely (abbrevp == (Dwarf_Abbrev *) -1l))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* Search the name attribute. */
unsigned char *const endp
= ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ dbg->sectiondata[IDX_debug_abbrev]->d_size);
unsigned char *attrp = abbrevp->attrp;
while (1)
{
/* Are we still in bounds? This test needs to be refined. */
if (unlikely (attrp + 1 >= endp))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* Get attribute name and form.
XXX We don't check whether this reads beyond the end of the
section. */
unsigned int attr_name;
get_uleb128 (attr_name, attrp);
unsigned int attr_form;
get_uleb128 (attr_form, attrp);
/* We can stop if we found the attribute with value zero. */
if (attr_name == 0 && attr_form == 0)
break;
/* Is this the name attribute? */
if (attr_name == search_name && search_name != INVALID)
{
if (codep != NULL)
*codep = attr_name;
if (formp != NULL)
*formp = attr_form;
return readp;
}
/* Skip over the rest of this attribute (if there is any). */
if (attr_form != 0)
{
size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp);
if (unlikely (len == (size_t) -1l))
return NULL;
// XXX We need better boundary checks.
readp += len;
}
}
// XXX Do we need other values?
if (codep != NULL)
*codep = INVALID;
if (formp != NULL)
*formp = INVALID;
return readp;
}
Dwarf_Die *
dwarf_child (die, result)
Dwarf_Die *die;
Dwarf_Die *result;
{
/* Ignore previous errors. */
if (die == NULL)
return NULL;
/* Skip past the last attribute. */
void *addr = NULL;
/* If we already know there are no children do not search. */
if (die->abbrev == NULL || die->abbrev->has_children)
addr = __libdw_find_attr (die, INVALID, NULL, NULL);
/* Make sure the DIE really has children. */
if (die->abbrev != NULL && ! die->abbrev->has_children)
/* There cannot be any children. But we may have found a sibling. */
return NULL;
if (addr == NULL)
return NULL;
/* Clear the entire DIE structure. This signals we have not yet
determined any of the information. */
memset (result, '\0', sizeof (Dwarf_Die));
/* We have the address. */
result->addr = addr;
/* Same CU as the parent. */
result->cu = die->cu;
return result;
}

View File

@ -0,0 +1,30 @@
/* Return string in name attribute of DIE.
Copyright (C) 2002 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
const char *
dwarf_diename (die)
Dwarf_Die *die;
{
Dwarf_Attribute attr_mem;
return dwarf_formstring (dwarf_attr (die, DW_AT_name, &attr_mem));
}

View File

@ -0,0 +1,43 @@
/* Return address represented by attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_formaddr (attr, return_addr)
Dwarf_Attribute *attr;
Dwarf_Addr *return_addr;
{
if (attr == NULL)
return -1;
if (unlikely (attr->form != DW_FORM_addr))
{
__libdw_seterrno (DWARF_E_NO_ADDR);
return -1;
}
if (attr->cu->address_size == 8)
*return_addr = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
else
*return_addr = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
return 0;
}

View File

@ -0,0 +1,68 @@
/* Return reference offset represented by attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_formref (attr, return_offset)
Dwarf_Attribute *attr;
Dwarf_Off *return_offset;
{
if (attr == NULL)
return -1;
unsigned int u128;
unsigned char *datap;
switch (attr->form)
{
case DW_FORM_ref1:
*return_offset = *attr->valp;
break;
case DW_FORM_ref2:
*return_offset = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_ref4:
*return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_ref8:
*return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_ref_udata:
datap = attr->valp;
get_uleb128 (u128, datap);
*return_offset = u128;
break;
case DW_FORM_ref_addr:
__libdw_seterrno (DWARF_E_INVALID_REFERENCE);
return -1;
default:
__libdw_seterrno (DWARF_E_NO_REFERENCE);
return -1;
}
return 0;
}

View File

@ -0,0 +1,70 @@
/* Return signed constant represented by attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_formsdata (attr, return_sval)
Dwarf_Attribute *attr;
Dwarf_Sword *return_sval;
{
if (attr == NULL)
return -1;
unsigned int u128;
unsigned char *datap;
switch (attr->form)
{
case DW_FORM_data1:
*return_sval = *attr->valp;
break;
case DW_FORM_data2:
*return_sval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_data4:
*return_sval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_data8:
*return_sval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_sdata:
datap = attr->valp;
get_sleb128 (u128, datap);
*return_sval = u128;
break;
case DW_FORM_udata:
datap = attr->valp;
get_uleb128 (u128, datap);
*return_sval = u128;
break;
default:
__libdw_seterrno (DWARF_E_NO_CONSTANT);
return -1;
}
return 0;
}

View File

@ -0,0 +1,57 @@
/* Return string associated with given attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
const char *
dwarf_formstring (attrp)
Dwarf_Attribute *attrp;
{
/* Ignore earlier errors. */
if (attrp == NULL)
return NULL;
/* We found it. Now determine where the string is stored. */
if (attrp->form == DW_FORM_string)
/* A simple inlined string. */
return (const char *) attrp->valp;
Dwarf *dbg = attrp->cu->dbg;
if (unlikely (attrp->form != DW_FORM_strp)
|| dbg->sectiondata[IDX_debug_str] == NULL)
{
invalid_error:
__libdw_seterrno (DWARF_E_NO_STRING);
return NULL;
}
uint64_t off;
// XXX We need better boundary checks.
if (attrp->cu->address_size == 8)
off = read_8ubyte_unaligned (dbg, attrp->valp);
else
off = read_4ubyte_unaligned (dbg, attrp->valp);
if (off >= dbg->sectiondata[IDX_debug_str]->d_size)
goto invalid_error;
return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off;
}

View File

@ -0,0 +1,70 @@
/* Return unsigned constant represented by attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_formudata (attr, return_uval)
Dwarf_Attribute *attr;
Dwarf_Word *return_uval;
{
if (attr == NULL)
return -1;
unsigned int u128;
unsigned char *datap;
switch (attr->form)
{
case DW_FORM_data1:
*return_uval = *attr->valp;
break;
case DW_FORM_data2:
*return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_data4:
*return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_data8:
*return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
break;
case DW_FORM_sdata:
datap = attr->valp;
get_sleb128 (u128, datap);
*return_uval = u128;
break;
case DW_FORM_udata:
datap = attr->valp;
get_uleb128 (u128, datap);
*return_uval = u128;
break;
default:
__libdw_seterrno (DWARF_E_NO_CONSTANT);
return -1;
}
return 0;
}

View File

@ -0,0 +1,106 @@
/* Get abbreviation at given offset.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <dwarf.h>
#include "libdwP.h"
Dwarf_Abbrev *
dwarf_get_abbrev (cu, offset, lengthp)
struct Dwarf_CU *cu;
Dwarf_Off offset;
size_t *lengthp;
{
/* Don't fail if there is not .debug_abbrev section. */
if (cu->dbg->sectiondata[IDX_debug_abbrev] == NULL)
return NULL;
char *abbrevp = ((char *) cu->dbg->sectiondata[IDX_debug_abbrev]->d_buf
+ offset);
char *start_abbrevp = abbrevp;
if (*abbrevp == '\0')
/* We are past the last entry. */
return NULL;
/* 7.5.3 Abbreviations Tables
[...] Each declaration begins with an unsigned LEB128 number
representing the abbreviation code itself. [...] The
abbreviation code is followed by another unsigned LEB128
number that encodes the entry's tag. [...]
[...] Following the tag encoding is a 1-byte value that
determines whether a debugging information entry using this
abbreviation has child entries or not. [...]
[...] Finally, the child encoding is followed by a series of
attribute specifications. Each attribute specification
consists of two parts. The first part is an unsigned LEB128
number representing the attribute's name. The second part is
an unsigned LEB128 number representing the attribute s form. */
unsigned int code;
get_uleb128 (code, abbrevp);
/* Check whether this code is already in the hash table. */
bool foundit = false;
Dwarf_Abbrev *abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL);
if (abb == NULL)
abb = libdw_alloc (cu->dbg, Dwarf_Abbrev);
else
{
foundit = true;
assert (abb->offset == offset);
/* If the caller doesn't need the length we are done. */
if (lengthp == NULL)
goto out;
}
/* If there is already a value in the hash table we are going to
overwrite its content. This must not be a problem, since the
content better be the same. */
abb->code = code;
get_uleb128 (abb->tag, abbrevp);
abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
abb->attrp = abbrevp;
abb->offset = offset;
/* Skip over all the attributes and count them while doing so. */
abb->attrcnt = 0;
unsigned int attrname;
unsigned int attrform;
do
{
get_uleb128 (attrname, abbrevp);
get_uleb128 (attrform, abbrevp);
}
while (attrname != 0 && attrform != 0 && ++abb->attrcnt);
/* Return the length to the caller if she asked for it. */
if (lengthp != NULL)
*lengthp = abbrevp - start_abbrevp;
/* Add the entry to the hash table. */
if (! foundit)
(void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb);
out:
return abb;
}

View File

@ -0,0 +1,48 @@
/* Return string associated with given attribute.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libdwP.h"
#include <string.h>
int
dwarf_has_children (die)
Dwarf_Die *die;
{
/* Find the abbreviation entry. */
Dwarf_Abbrev *abbrevp = die->abbrev;
if (abbrevp != (Dwarf_Abbrev *) -1l)
{
unsigned char *readp = (unsigned char *) die->addr;
/* First we have to get the abbreviation code so that we can decode
the data in the DIE. */
unsigned int abbrev_code;
get_uleb128 (abbrev_code, readp);
abbrevp = __libdw_getabbrev (die->cu, abbrev_code);
die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
}
if (unlikely (abbrevp == (Dwarf_Abbrev *) -1l))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return 0;
}
return abbrevp->has_children;
}

View File

@ -0,0 +1,32 @@
/* Return high PC attribute of DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_highpc (die, return_addr)
Dwarf_Die *die;
Dwarf_Addr *return_addr;
{
Dwarf_Attribute attr_mem;
return dwarf_formaddr (dwarf_attr (die, DW_AT_high_pc, &attr_mem),
return_addr);
}

View File

@ -0,0 +1,32 @@
/* Return low PC attribute of DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
int
dwarf_lowpc (die, return_addr)
Dwarf_Die *die;
Dwarf_Addr *return_addr;
{
Dwarf_Attribute attr_mem;
return dwarf_formaddr (dwarf_attr (die, DW_AT_low_pc, &attr_mem),
return_addr);
}

View File

@ -0,0 +1,135 @@
/* Advance to next CU header.
Copyright (C) 2002, 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
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, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <libdwP.h>
int
dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
address_sizep)
Dwarf *dwarf;
Dwarf_Off off;
Dwarf_Off *next_off;
size_t *header_sizep;
Dwarf_Off *abbrev_offsetp;
uint8_t *address_sizep;
{
/* Maybe there has been an error before. */
if (dwarf == NULL)
return 0;
/* If we reached the end before don't do anything. */
if (off == (Dwarf_Off) -1l
/* Make sure there is enough space in the .debug_info section
for at least the initial word. We cannot test the rest since
we don't know yet whether this is a 64-bit object or not. */
|| unlikely (off + 4 >= dwarf->sectiondata[IDX_debug_info]->d_size))
{
*next_off = (Dwarf_Off) -1l;
return 1;
}
/* This points into the .debug_info section to the beginning of the
CU entry. */
char *bytes = (char *) dwarf->sectiondata[IDX_debug_info]->d_buf + off;
/* The format of the CU header is described in dwarf2p1 7.5.1:
1. A 4-byte or 12-byte unsigned integer representing the length
of the .debug_info contribution for that compilation unit, not
including the length field itself. In the 32-bit DWARF format,
this is a 4-byte unsigned integer (which must be less than
0xffffff00); in the 64-bit DWARF format, this consists of the
4-byte value 0xffffffff followed by an 8-byte unsigned integer
that gives the actual length (see Section 7.4).
2. A 2-byte unsigned integer representing the version of the
DWARF information for that compilation unit. For DWARF Version
2.1, the value in this field is 2.
3. A 4-byte or 8-byte unsigned offset into the .debug_abbrev
section. This offset associates the compilation unit with a
particular set of debugging information entry abbreviations. In
the 32-bit DWARF format, this is a 4-byte unsigned length; in
the 64-bit DWARF format, this is an 8-byte unsigned length (see
Section 7.4).
4. A 1-byte unsigned integer representing the size in bytes of
an address on the target architecture. If the system uses
segmented addressing, this value represents the size of the
offset portion of an address. */
uint64_t length = read_4ubyte_unaligned (dwarf, bytes);
bytes += 4;
size_t offset_size = 4;
if (length == 0xffffffffu)
offset_size = 8;
/* Now we know how large the header is. Note the trick in the
computation. If the offset_size is 4 the '- 4' term undoes the
'2 *'. If offset_size is 8 this term computes the size of the
escape value plus the 8 byte offset. */
if (unlikely (off + 2 * offset_size - 4 + sizeof (uint16_t)
+ offset_size + sizeof (uint8_t)
>= dwarf->sectiondata[IDX_debug_info]->d_size))
{
*next_off = -1;
return 1;
}
if (length == 0xffffffffu)
{
/* This is a 64-bit DWARF format. */
length = read_8ubyte_unaligned (dwarf, bytes);
bytes += 8;
}
/* Read the version stamp. Always a 16-bit value.
XXX Do we need the value? */
read_2ubyte_unaligned (dwarf, bytes);
bytes += 2;
/* Get offset in .debug_abbrev. Note that the size of the entry
depends on whether this is a 32-bit or 64-bit DWARF definition. */
uint64_t abbrev_offset;
if (offset_size == 4)
abbrev_offset = read_4ubyte_unaligned (dwarf, bytes);
else
abbrev_offset = read_8ubyte_unaligned (dwarf, bytes);
if (abbrev_offsetp != NULL)
*abbrev_offsetp = abbrev_offset;
bytes += offset_size;
/* The address size. Always an 8-bit value. */
uint8_t address_size = *bytes++;
if (address_sizep != NULL)
*address_sizep = address_size;
/* Store the header length. */
if (header_sizep != NULL)
*header_sizep = (bytes
- ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf
+ off));
/* See above for an explanation of the trick in this formula. */
*next_off = off + 2 * offset_size - 4 + length;
return 0;
}

View File

@ -0,0 +1,54 @@
/* Return DIE at given offset.
Copyright (C) 2002, 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include "libdwP.h"
Dwarf_Die *
dwarf_offdie (dbg, offset, result)
Dwarf *dbg;
Dwarf_Off offset;
Dwarf_Die *result;
{
if (dbg == NULL)
return NULL;
if (offset >= dbg->sectiondata[IDX_debug_info]->d_size)
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* Clear the entire DIE structure. This signals we have not yet
determined any of the information. */
memset (result, '\0', sizeof (Dwarf_Die));
result->addr = (char *) dbg->sectiondata[IDX_debug_info]->d_buf + offset;
/* Get the CU. */
result->cu = __libdw_findcu (dbg, offset);
if (result->cu == NULL)
{
/* This should never happen. The input file is malformed. */
__libdw_seterrno (DWARF_E_INVALID_DWARF);
result = NULL;
}
return result;
}

View File

@ -0,0 +1,116 @@
/* Return sibling of given DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libdwP.h"
#include <dwarf.h>
#include <string.h>
Dwarf_Die *
dwarf_siblingof (die, result)
Dwarf_Die *die;
Dwarf_Die *result;
{
/* Ignore previous errors. */
if (die == NULL)
return NULL;
unsigned int level = 0;
/* The address we are looking at. */
unsigned char *addr = die->addr;
/* Copy of the current DIE. */
Dwarf_Die this_die = *die;
/* Search for the beginning of the next die on this level. We
must not return the dies for children of the given die. */
do
{
/* Get the abbreviation code. */
unsigned int abbrev_code;
get_uleb128 (abbrev_code, addr);
if (this_die.abbrev == NULL)
{
this_die.abbrev = __libdw_getabbrev (die->cu, abbrev_code);
if (this_die.abbrev == NULL)
this_die.abbrev = (Dwarf_Abbrev *) -1l;
}
if (unlikely (this_die.abbrev == (Dwarf_Abbrev *) -1l))
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* Does this abbreviation have children? */
if (this_die.abbrev->has_children)
++level;
/* Find the end of the DIE or the sibling attribute. */
unsigned int code;
addr = __libdw_find_attr (&this_die, DW_AT_sibling, &code, NULL);
if (code == DW_AT_sibling)
{
Dwarf_Off offset;
Dwarf_Attribute sibattr;
sibattr.valp = addr;
sibattr.cu = die->cu;
if (dwarf_formref (&sibattr, &offset) != 0)
/* Something went wrong. */
return NULL;
/* Compute the next address. */
addr
= ((unsigned char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
+ die->cu->start + offset);
/* Even if the abbreviation has children we have stepped
over them now. */
if (this_die.abbrev->has_children)
--level;
}
/* Check that we are not yet at the end. */
while (*addr == '\0')
{
if (level-- == 0)
/* No more sibling at all. */
return DWARF_END_DIE;
++addr;
}
/* Initialize the 'current DIE'. */
this_die.addr = addr;
this_die.abbrev = NULL;
}
while (level > 0);
/* Clear the entire DIE structure. This signals we have not yet
determined any of the information. */
memset (result, '\0', sizeof (Dwarf_Die));
/* We have the address. */
result->addr = addr;
/* Same CU as the parent. */
result->cu = die->cu;
return result;
}

View File

@ -0,0 +1,82 @@
/* Return tag of given DIE.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libdwP.h"
Dwarf_Abbrev *
internal_function
__libdw_getabbrev (struct Dwarf_CU *cu, unsigned int code)
{
Dwarf_Abbrev *abb;
/* See whether the entry is already in the hash table. */
abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL);
if (abb == NULL)
while (cu->last_abbrev_offset != (size_t) -1l)
{
size_t length;
/* Find the next entry. It gets automatically added to the
hash table. */
abb = dwarf_get_abbrev (cu, cu->last_abbrev_offset, &length);
if (abb == NULL)
{
/* Make sure we do not try to search for it again. */
cu->last_abbrev_offset = (size_t) -1l;
break;
}
cu->last_abbrev_offset += length;
/* Is this the code we are looking for? */
if (abb->code == code)
break;
}
return abb;
}
int
dwarf_tag (die)
Dwarf_Die *die;
{
/* Do we already know the abbreviation? */
if (die->abbrev == NULL)
{
/* Check that we have not done this before. */
if (die->abbrev != (Dwarf_Abbrev *) -1l)
{
/* Get the abbreviation code. */
unsigned int u128;
get_uleb128 (u128, die->addr);
/* Find the abbreviation. */
die->abbrev = __libdw_getabbrev (die->cu, u128);
}
if (die->abbrev == (Dwarf_Abbrev *) -1l)
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return DW_TAG_invalid;
}
}
return die->abbrev->tag;
}

View File

@ -0,0 +1,63 @@
/* Memory handling for libdw.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
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, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <error.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/param.h>
#include "libdwP.h"
void *
__libdw_allocate (Dwarf *dbg, size_t minsize)
{
size_t size = MAX (dbg->mem_default_size,
2 * minsize + offsetof (struct libdw_memblock, mem));
struct libdw_memblock *newp = malloc (size);
if (newp == NULL)
dbg->oom_handler ();
newp->size = newp->remaining = size - offsetof (struct libdw_memblock, mem);
newp->prev = dbg->mem_tail;
newp->next = NULL;
dbg->mem_tail = newp;
return newp->mem;
}
Dwarf_OOM
dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler)
{
Dwarf_OOM old = dbg->oom_handler;
dbg->oom_handler = handler;
return old;
}
void
__attribute ((noreturn, visibility ("hidden")))
__libdw_oom (void)
{
while (1)
error (EXIT_FAILURE, ENOMEM, "libdw");
}

View File

@ -0,0 +1,108 @@
/* Find CU for given offset.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
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, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <search.h>
#include "libdwP.h"
static int
findcu_cb (const void *arg1, const void *arg2)
{
struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
/* Find out which of the two arguments is the search value. It has
length 0. */
if (cu1->length == 0)
{
if (cu1->start < cu2->start)
return -1;
if (cu1->start >= cu2->start + cu2->length)
return 1;
}
else
{
if (cu2->start < cu1->start)
return 1;
if (cu2->start >= cu1->start + cu1->length)
return -1;
}
return 0;
}
struct Dwarf_CU *
__libdw_findcu (dbg, start)
Dwarf *dbg;
Dwarf_Off start;
{
/* Maybe we already know that CU. */
struct Dwarf_CU fake = { .start = start, .length = 0 };
struct Dwarf_CU **found = tfind (&fake, &dbg->cu_tree, findcu_cb);
if (found != NULL)
return *found;
if (start < dbg->next_cu_offset)
{
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* No. Then read more CUs. */
while (1)
{
Dwarf_Off oldoff = dbg->next_cu_offset;
uint8_t address_size;
Dwarf_Off abbrev_offset;
if (dwarf_nextcu (dbg, oldoff, &dbg->next_cu_offset, NULL,
&abbrev_offset, &address_size) != 0)
/* No more entries. */
return NULL;
/* Create an entry for this CU. */
struct Dwarf_CU *newp = libdw_alloc (dbg, struct Dwarf_CU);
newp->dbg = dbg;
newp->start = oldoff;
newp->length = dbg->next_cu_offset - oldoff;
newp->address_size = address_size;
Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
newp->last_abbrev_offset = abbrev_offset;
/* Add the new entry to the search tree. */
if (tsearch (newp, &dbg->cu_tree, findcu_cb) == NULL)
{
/* Something went wrong. Unfo the operation. */
dbg->next_cu_offset = oldoff;
__libdw_seterrno (DWARF_E_NOMEM);
return NULL;
}
/* Is this the one we are looking for? */
if (start < dbg->next_cu_offset)
// XXX Match exact offset.
return newp;
}
/* NOTREACHED */
}

109
elfutils/libdw/libdw_form.c Normal file
View File

@ -0,0 +1,109 @@
/* Helper functions for form handling.
Copyright (C) 2003 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2003.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include <string.h>
#include "libdwP.h"
size_t
internal_function
__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form,
unsigned char *valp)
{
unsigned char *saved;
unsigned int u128;
size_t result;
switch (form)
{
case DW_FORM_addr:
case DW_FORM_strp:
case DW_FORM_ref_addr:
result = cu->address_size;
break;
case DW_FORM_block1:
result = *valp + 1;
break;
case DW_FORM_block2:
result = read_2ubyte_unaligned (dbg, valp) + 2;
break;
case DW_FORM_block4:
result = read_4ubyte_unaligned (dbg, valp) + 4;
break;
case DW_FORM_block:
saved = valp;
get_uleb128 (u128, valp);
result = u128 + (valp - saved);
break;
case DW_FORM_ref1:
case DW_FORM_data1:
case DW_FORM_flag:
result = 1;
break;
case DW_FORM_data2:
case DW_FORM_ref2:
result = 2;
break;
case DW_FORM_data4:
case DW_FORM_ref4:
result = 4;
break;
case DW_FORM_data8:
case DW_FORM_ref8:
result = 8;
break;
case DW_FORM_string:
result = strlen ((char *) valp) + 1;
break;
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
saved = valp;
get_uleb128 (u128, valp);
result = valp - saved;
break;
case DW_FORM_indirect:
saved = valp;
get_uleb128 (u128, valp);
// XXX Is this really correct?
result = __libdw_form_val_len (dbg, cu, u128, valp);
if (result != (size_t) -1)
result += valp - saved;
break;
default:
__libdw_seterrno (DWARF_E_INVALID_DWARF);
result = (size_t) -1l;
break;
}
return result;
}