summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf/dwarf/common/dwarf_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_util.c')
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_util.c547
1 files changed, 0 insertions, 547 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_util.c b/usr/src/tools/ctf/dwarf/common/dwarf_util.c
deleted file mode 100644
index 01e0dd755d..0000000000
--- a/usr/src/tools/ctf/dwarf/common/dwarf_util.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
- Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
-
- This program is free software; you can redistribute it and/or modify it
- 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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
- USA.
-
- Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
- Mountain View, CA 94043, or:
-
- http://www.sgi.com
-
- For further information regarding this notice, see:
-
- http://oss.sgi.com/projects/GenInfo/NoticeExplan
-
-*/
-/* The address of the Free Software Foundation is
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- Boston, MA 02110-1301, USA.
- SGI has moved from the Crittenden Lane address.
-*/
-
-
-
-
-
-#include "config.h"
-#include "dwarf_incl.h"
-#include <stdio.h>
-#include "dwarf_die_deliv.h"
-
-
-
-/*
- Given a form, and a pointer to the bytes encoding
- a value of that form, val_ptr, this function returns
- the length, in bytes, of a value of that form.
- When using this function, check for a return of 0
- a recursive DW_FORM_INDIRECT value.
-*/
-Dwarf_Unsigned
-_dwarf_get_size_of_val(Dwarf_Debug dbg,
- Dwarf_Unsigned form,
- Dwarf_Half address_size,
- Dwarf_Small * val_ptr, int v_length_size)
-{
- Dwarf_Unsigned length = 0;
- Dwarf_Word leb128_length = 0;
- Dwarf_Unsigned form_indirect = 0;
- Dwarf_Unsigned ret_value = 0;
-
- switch (form) {
-
- default: /* Handles form = 0. */
- return (form);
-
- case DW_FORM_addr:
- if(address_size) {
- return address_size;
- }
- /* This should never happen, address_size should be set. */
- return (dbg->de_pointer_size);
-
- /* DWARF2 was wrong on the size of the attribute for
- DW_FORM_ref_addr. We assume compilers are using the
- corrected DWARF3 text (for 32bit pointer target objects pointer and
- offsets are the same size anyway). */
- case DW_FORM_ref_addr:
- return (v_length_size);
-
- case DW_FORM_block1:
- return (*(Dwarf_Small *) val_ptr + 1);
-
- case DW_FORM_block2:
- READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
- val_ptr, sizeof(Dwarf_Half));
- return (ret_value + sizeof(Dwarf_Half));
-
- case DW_FORM_block4:
- READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
- val_ptr, sizeof(Dwarf_ufixed));
- return (ret_value + sizeof(Dwarf_ufixed));
-
-
- case DW_FORM_data1:
- return (1);
-
- case DW_FORM_data2:
- return (2);
-
- case DW_FORM_data4:
- return (4);
-
- case DW_FORM_data8:
- return (8);
-
- case DW_FORM_string:
- return (strlen((char *) val_ptr) + 1);
-
- case DW_FORM_block:
- case DW_FORM_exprloc:
- length = _dwarf_decode_u_leb128(val_ptr, &leb128_length);
- return (length + leb128_length);
-
- case DW_FORM_flag_present:
- return (0);
- case DW_FORM_flag:
- return (1);
-
- case DW_FORM_sec_offset:
- /* If 32bit dwarf, is 4. Else is 64bit dwarf and is 8. */
- return (v_length_size);
-
- case DW_FORM_ref_udata:
- length = _dwarf_decode_u_leb128(val_ptr, &leb128_length);
- return (leb128_length);
-
- case DW_FORM_indirect:
- {
- Dwarf_Word indir_len = 0;
-
- form_indirect = _dwarf_decode_u_leb128(val_ptr, &indir_len);
- if (form_indirect == DW_FORM_indirect) {
- return (0); /* We are in big trouble: The true form
- of DW_FORM_indirect is
- DW_FORM_indirect? Nonsense. Should
- never happen. */
- }
- return (indir_len + _dwarf_get_size_of_val(dbg,
- form_indirect,
- address_size,
- val_ptr + indir_len,
- v_length_size));
- }
-
- case DW_FORM_ref1:
- return (1);
-
- case DW_FORM_ref2:
- return (2);
-
- case DW_FORM_ref4:
- return (4);
-
- case DW_FORM_ref8:
- return (8);
-
- case DW_FORM_sdata:
- _dwarf_decode_s_leb128(val_ptr, &leb128_length);
- return (leb128_length);
-
- case DW_FORM_strp:
- return (v_length_size);
-
- case DW_FORM_udata:
- _dwarf_decode_u_leb128(val_ptr, &leb128_length);
- return (leb128_length);
- }
-}
-
-/* We allow an arbitrary number of HT_MULTIPLE entries
- before resizing. It seems up to 20 or 30
- would work nearly as well.
- We could have a different resize multiple than 'resize now'
- test multiple, but for now we don't do that.
-*/
-#define HT_MULTIPLE 8
-
-/* Copy the old entries, updating each to be in
- a new list. Don't delete anything. Leave the
- htin with stale data. */
-static void
-copy_abbrev_table_to_new_table(Dwarf_Hash_Table htin,
- Dwarf_Hash_Table htout)
-{
- Dwarf_Hash_Table_Entry entry_in = htin->tb_entries;
- unsigned entry_in_count = htin->tb_table_entry_count;
- Dwarf_Hash_Table_Entry entry_out = htout->tb_entries;
- unsigned entry_out_count = htout->tb_table_entry_count;
- unsigned k = 0;
- for ( ; k < entry_in_count; ++k,++entry_in) {
- Dwarf_Abbrev_List listent = entry_in->at_head;
- Dwarf_Abbrev_List nextlistent = 0;
-
- for ( ; listent ; listent = nextlistent) {
- unsigned newtmp = listent->ab_code;
- unsigned newhash = newtmp%entry_out_count;
- Dwarf_Hash_Table_Entry e;
- nextlistent = listent->ab_next;
- e = entry_out+newhash;
- /* Move_entry_to_new_hash. This reverses the
- order of the entries, effectively, but
- that does not seem significant. */
- listent->ab_next = e->at_head;
- e->at_head = listent;
-
- htout->tb_total_abbrev_count++;
- }
- }
-}
-
-/*
- This function returns a pointer to a Dwarf_Abbrev_List_s
- struct for the abbrev with the given code. It puts the
- struct on the appropriate hash table. It also adds all
- the abbrev between the last abbrev added and this one to
- the hash table. In other words, the .debug_abbrev section
- is scanned sequentially from the top for an abbrev with
- the given code. All intervening abbrevs are also put
- into the hash table.
-
- This function hashes the given code, and checks the chain
- at that hash table entry to see if a Dwarf_Abbrev_List_s
- with the given code exists. If yes, it returns a pointer
- to that struct. Otherwise, it scans the .debug_abbrev
- section from the last byte scanned for that CU till either
- an abbrev with the given code is found, or an abbrev code
- of 0 is read. It puts Dwarf_Abbrev_List_s entries for all
- abbrev's read till that point into the hash table. The
- hash table contains both a head pointer and a tail pointer
- for each entry.
-
- While the lists can move and entries can be moved between
- lists on reallocation, any given Dwarf_Abbrev_list entry
- never moves once allocated, so the pointer is safe to return.
-
- Returns NULL on error.
-*/
-Dwarf_Abbrev_List
-_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code)
-{
- Dwarf_Debug dbg = cu_context->cc_dbg;
- Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table;
- Dwarf_Hash_Table_Entry entry_base = 0;
- Dwarf_Hash_Table_Entry entry_cur = 0;
- Dwarf_Word hash_num = 0;
- Dwarf_Unsigned abbrev_code = 0;
- Dwarf_Unsigned abbrev_tag = 0;
- Dwarf_Unsigned attr_name = 0;
- Dwarf_Unsigned attr_form = 0;
-
- Dwarf_Abbrev_List hash_abbrev_entry = 0;
-
- Dwarf_Abbrev_List inner_list_entry = 0;
- Dwarf_Hash_Table_Entry inner_hash_entry = 0;
-
- Dwarf_Byte_Ptr abbrev_ptr = 0;
- unsigned hashable_val;
-
- if ( !hash_table_base->tb_entries ) {
- hash_table_base->tb_table_entry_count = HT_MULTIPLE;
- hash_table_base->tb_total_abbrev_count= 0;
- hash_table_base->tb_entries = _dwarf_get_alloc(dbg,
- DW_DLA_HASH_TABLE_ENTRY,
- hash_table_base->tb_table_entry_count);
- if(! hash_table_base->tb_entries) {
- return NULL;
- }
-
- } else if (hash_table_base->tb_total_abbrev_count >
- ( hash_table_base->tb_table_entry_count * HT_MULTIPLE) ) {
- struct Dwarf_Hash_Table_s newht;
- /* Effectively multiplies by >= HT_MULTIPLE */
- newht.tb_table_entry_count = hash_table_base->tb_total_abbrev_count;
- newht.tb_total_abbrev_count = 0;
- newht.tb_entries = _dwarf_get_alloc(dbg,
- DW_DLA_HASH_TABLE_ENTRY,
- newht.tb_table_entry_count);
-
- if(! newht.tb_entries) {
- return NULL;
- }
- /* Copy the existing entries to the new table,
- rehashing each.
- */
- copy_abbrev_table_to_new_table(hash_table_base, &newht);
- /* Dealloc only the entries hash table array, not the lists
- of things pointed to by a hash table entry array. */
- dwarf_dealloc(dbg, hash_table_base->tb_entries,DW_DLA_HASH_TABLE_ENTRY);
- hash_table_base->tb_entries = 0;
- /* Now overwrite the existing table descriptor with
- the new, newly valid, contents. */
- *hash_table_base = newht;
- } /* Else is ok as is, add entry */
-
-
- hashable_val = code;
- hash_num = hashable_val %
- hash_table_base->tb_table_entry_count;
- entry_base = hash_table_base->tb_entries;
- entry_cur = entry_base + hash_num;
-
- /* Determine if the 'code' is the list of synonyms already. */
- for (hash_abbrev_entry = entry_cur->at_head;
- hash_abbrev_entry != NULL && hash_abbrev_entry->ab_code != code;
- hash_abbrev_entry = hash_abbrev_entry->ab_next);
- if (hash_abbrev_entry != NULL) {
- /* This returns a pointer to an abbrev list entry, not
- the list itself. */
- return (hash_abbrev_entry);
- }
-
- abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ?
- cu_context->cc_last_abbrev_ptr :
- dbg->de_debug_abbrev.dss_data + cu_context->cc_abbrev_offset;
-
- /* End of abbrev's for this cu, since abbrev code is 0. */
- if (*abbrev_ptr == 0) {
- return (NULL);
- }
-
- do {
- unsigned new_hashable_val;
- DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code);
- DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag);
-
- inner_list_entry = (Dwarf_Abbrev_List)
- _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1);
- if (inner_list_entry == NULL)
- return (NULL);
-
- new_hashable_val = abbrev_code;
- hash_num = new_hashable_val %
- hash_table_base->tb_table_entry_count;
- inner_hash_entry = entry_base + hash_num;
- /* Move_entry_to_new_hash */
- inner_list_entry->ab_next = inner_hash_entry->at_head;
- inner_hash_entry->at_head = inner_list_entry;
-
- hash_table_base->tb_total_abbrev_count++;
-
- inner_list_entry->ab_code = abbrev_code;
- inner_list_entry->ab_tag = abbrev_tag;
- inner_list_entry->ab_has_child = *(abbrev_ptr++);
- inner_list_entry->ab_abbrev_ptr = abbrev_ptr;
-
- /* Cycle thru the abbrev content, ignoring the content except
- to find the end of the content. */
- do {
- DECODE_LEB128_UWORD(abbrev_ptr, attr_name);
- DECODE_LEB128_UWORD(abbrev_ptr, attr_form);
- } while (attr_name != 0 && attr_form != 0);
-
- } while (*abbrev_ptr != 0 && abbrev_code != code);
-
- cu_context->cc_last_abbrev_ptr = abbrev_ptr;
- return (abbrev_code == code ? inner_list_entry : NULL);
-}
-
-
-/* return 1 if string ends before 'endptr' else
-** return 0 meaning string is not properly terminated.
-** Presumption is the 'endptr' pts to end of some dwarf section data.
-*/
-int
-_dwarf_string_valid(void *startptr, void *endptr)
-{
-
- char *start = startptr;
- char *end = endptr;
-
- while (start < end) {
- if (*start == 0) {
- return 1; /* OK! */
- }
- ++start;
- ++end;
- }
- return 0; /* FAIL! bad string! */
-}
-
-/*
- A byte-swapping version of memcpy
- for cross-endian use.
- Only 2,4,8 should be lengths passed in.
-*/
-void *
-_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len)
-{
- void *orig_s1 = s1;
- unsigned char *targ = (unsigned char *) s1;
- unsigned char *src = (unsigned char *) s2;
-
- if (len == 4) {
- targ[3] = src[0];
- targ[2] = src[1];
- targ[1] = src[2];
- targ[0] = src[3];
- } else if (len == 8) {
- targ[7] = src[0];
- targ[6] = src[1];
- targ[5] = src[2];
- targ[4] = src[3];
- targ[3] = src[4];
- targ[2] = src[5];
- targ[1] = src[6];
- targ[0] = src[7];
- } else if (len == 2) {
- targ[1] = src[0];
- targ[0] = src[1];
- }
-/* should NOT get below here: is not the intended use */
- else if (len == 1) {
- targ[0] = src[0];
- } else {
- memcpy(s1, s2, len);
- }
-
- return orig_s1;
-}
-
-
-/*
- This calculation used to be sprinkled all over.
- Now brought to one place.
-
- We try to accurately compute the size of a cu header
- given a known cu header location ( an offset in .debug_info).
-
-*/
-/* ARGSUSED */
-Dwarf_Unsigned
-_dwarf_length_of_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned offset)
-{
- int local_length_size = 0;
- int local_extension_size = 0;
- Dwarf_Unsigned length = 0;
- Dwarf_Small *cuptr = dbg->de_debug_info.dss_data + offset;
-
- READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
- cuptr, local_length_size, local_extension_size);
-
- return local_extension_size + /* initial extesion, if present
- */
- local_length_size + /* Size of cu length field. */
- sizeof(Dwarf_Half) + /* Size of version stamp field. */
- local_length_size + /* Size of abbrev offset field. */
- sizeof(Dwarf_Small); /* Size of address size field. */
-
-}
-
-/*
- Pretend we know nothing about the CU
- and just roughly compute the result.
-*/
-Dwarf_Unsigned
-_dwarf_length_of_cu_header_simple(Dwarf_Debug dbg)
-{
- return dbg->de_length_size + /* Size of cu length field. */
- sizeof(Dwarf_Half) + /* Size of version stamp field. */
- dbg->de_length_size + /* Size of abbrev offset field. */
- sizeof(Dwarf_Small); /* Size of address size field. */
-}
-
-/* Now that we delay loading .debug_info, we need to do the
- load in more places. So putting the load
- code in one place now instead of replicating it in multiple
- places.
-
-*/
-int
-_dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error)
-{
- int res = DW_DLV_ERROR;
-
- /* Testing de_debug_info.dss_data allows us to avoid testing
- de_debug_abbrev.dss_data.
- One test instead of 2. .debug_info is useless
- without .debug_abbrev. */
- if (dbg->de_debug_info.dss_data) {
- return DW_DLV_OK;
- }
-
- res = _dwarf_load_section(dbg, &dbg->de_debug_abbrev,error);
- if (res != DW_DLV_OK) {
- return res;
- }
- res = _dwarf_load_section(dbg, &dbg->de_debug_info, error);
- return res;
-
-}
-void
-_dwarf_free_abbrev_hash_table_contents(Dwarf_Debug dbg,Dwarf_Hash_Table hash_table)
-{
- /* A Hash Table is an array with tb_table_entry_count struct
- Dwarf_Hash_Table_s entries in the array. */
- int hashnum = 0;
- for (; hashnum < hash_table->tb_table_entry_count; ++hashnum) {
- struct Dwarf_Abbrev_List_s *abbrev = 0;
- struct Dwarf_Abbrev_List_s *nextabbrev = 0;
- struct Dwarf_Hash_Table_Entry_s *tb = &hash_table->tb_entries[hashnum];
-
- abbrev = tb->at_head;
- for (; abbrev; abbrev = nextabbrev) {
- nextabbrev = abbrev->ab_next;
- dwarf_dealloc(dbg, abbrev, DW_DLA_ABBREV_LIST);
- }
- }
- /* Frees all the entries at once: an array. */
- dwarf_dealloc(dbg,hash_table->tb_entries,DW_DLA_HASH_TABLE_ENTRY);
-}
-
-/*
- If no die provided the size value returned might be wrong.
- If different compilation units have different address sizes
- this may not give the correct value in all contexts if the die
- pointer is NULL.
- If the Elf offset size != address_size
- (for example if address_size = 4 but recorded in elf64 object)
- this may not give the correct value in all contexts if the die
- pointer is NULL.
- If the die pointer is non-NULL (in which case it must point to
- a valid DIE) this will return the correct size.
-*/
-int
-_dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die)
-{
- Dwarf_CU_Context context = 0;
- Dwarf_Half addrsize = 0;
- if(!die) {
- return dbg->de_pointer_size;
- }
- context = die->di_cu_context;
- addrsize = context->cc_address_size;
- return addrsize;
-}
-
-
-