diff options
Diffstat (limited to 'libdwarf/pro_macinfo.c')
-rw-r--r-- | libdwarf/pro_macinfo.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/libdwarf/pro_macinfo.c b/libdwarf/pro_macinfo.c new file mode 100644 index 0000000..7985262 --- /dev/null +++ b/libdwarf/pro_macinfo.c @@ -0,0 +1,468 @@ +/* + + Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. + Portions Copyright 2011 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 + +*/ + + + +#include "config.h" +#include "libdwarfdefs.h" +#include <stdio.h> +#include <string.h> +#include "pro_incl.h" +#include "pro_section.h" +#include "pro_macinfo.h" + +/* I don't much like the error strings this generates, since + like the rest of libdwarf they are simple strings with + no useful numbers in them. But that's not something I can + fix without more work than I have time for + right now. davea Nov 94. +*/ + +/* these are gross overestimates of the number of +** bytes needed to store a number in LEB form. +** Just estimates, and since blocks are reasonable size, +** the end-block waste is small. +** Of course the waste is NOT present on disk. +*/ + +#define COMMAND_LEN ENCODE_SPACE_NEEDED +#define LINE_LEN ENCODE_SPACE_NEEDED +#define BASE_MACINFO_MALLOC_LEN 2048 + +static int +libdwarf_compose_begin(Dwarf_P_Debug dbg, int code, + size_t maxlen, int *compose_error_type) +{ + unsigned char *nextchar; + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + + if (curblk == 0) { + struct dw_macinfo_block_s *newb; + size_t len; + + /* initial allocation */ + size_t blen = BASE_MACINFO_MALLOC_LEN; + + if (blen < maxlen) { + blen = 2 * maxlen; + } + len = sizeof(struct dw_macinfo_block_s) + blen; + newb = + (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); + if (!newb) { + *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; + return DW_DLV_ERROR; + } + newb->mb_data = + (char *) newb + sizeof(struct dw_macinfo_block_s); + newb->mb_avail_len = blen; + newb->mb_used_len = 0; + newb->mb_macinfo_data_space_len = blen; + dbg->de_first_macinfo = newb; + dbg->de_current_macinfo = newb; + curblk = newb; + } else if (curblk->mb_avail_len < maxlen) { + struct dw_macinfo_block_s *newb; + size_t len; + + /* no space left in block: allocate a new block */ + size_t blen = + dbg->de_current_macinfo->mb_macinfo_data_space_len * 2; + if (blen < maxlen) { + blen = 2 * maxlen; + } + len = sizeof(struct dw_macinfo_block_s) + blen; + newb = + (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len); + if (!newb) { + *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL; + return DW_DLV_ERROR; + } + newb->mb_data = + (char *) newb + sizeof(struct dw_macinfo_block_s); + newb->mb_avail_len = blen; + newb->mb_used_len = 0; + newb->mb_macinfo_data_space_len = blen; + dbg->de_first_macinfo->mb_next = newb; + dbg->de_current_macinfo = newb; + curblk = newb; + } + /* now curblk has enough room */ + dbg->de_compose_avail = curblk->mb_avail_len; + dbg->de_compose_used_len = curblk->mb_used_len; + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + *nextchar = code; + dbg->de_compose_avail--; + ++dbg->de_compose_used_len; + return DW_DLV_OK; +} + + + +static void +libdwarf_compose_add_string(Dwarf_P_Debug dbg, char *string, size_t len) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + unsigned char *nextchar; + + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + + len += 1; /* count the null terminator */ + + memcpy(nextchar, string, len); + dbg->de_compose_avail -= len; + dbg->de_compose_used_len += len; + return; + +} +static int +libdwarf_compose_add_line(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, int *compose_error_type) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + unsigned char *nextchar; + int res; + int nbytes; + + nextchar = + (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len); + + /* Put the created leb number directly into the macro buffer If + dbg->de_compose_avail is > INT_MAX this will not work as the + 'int' will look negative to _dwarf_pro_encode_leb128_nm! */ + + res = _dwarf_pro_encode_leb128_nm(line, &nbytes, + (char *) nextchar, + (int) dbg->de_compose_avail); + if (res != DW_DLV_OK) { + *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; + return DW_DLV_ERROR; + } + + dbg->de_compose_avail -= nbytes; + dbg->de_compose_used_len += nbytes; + return DW_DLV_OK; +} + +/* This function actually 'commits' the space used by the + preceeding calls. */ +static int +libdwarf_compose_complete(Dwarf_P_Debug dbg, int *compose_error_type) +{ + struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo; + + if (dbg->de_compose_used_len > curblk->mb_macinfo_data_space_len) { + *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE; + return DW_DLV_ERROR; + } + curblk->mb_avail_len = dbg->de_compose_avail; + curblk->mb_used_len = dbg->de_compose_used_len; + return DW_DLV_OK; +} + + + +int +dwarf_def_macro(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, + char *macname, char *macvalue, Dwarf_Error * error) +{ + size_t len; + size_t len2; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (macname == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(macname) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + if (macvalue) { + len2 = strlen(macvalue) + 1; + } else { + len2 = 0; + } + + /* 1 for space character we add */ + length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1; + + res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, line, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, macname, len); + libdwarf_compose_add_string(dbg, " ", 1); + if (macvalue) { + libdwarf_compose_add_string(dbg, " ", 1); + libdwarf_compose_add_string(dbg, macvalue, len2); + } + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_undef_macro(Dwarf_P_Debug dbg, + Dwarf_Unsigned line, + char *macname, Dwarf_Error * error) +{ + + size_t len; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (macname == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(macname) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + len; + res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, line, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, macname, len); + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_start_macro_file(Dwarf_P_Debug dbg, + Dwarf_Unsigned fileindex, + Dwarf_Unsigned linenumber, Dwarf_Error * error) +{ + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + LINE_LEN; + res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, fileindex, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, linenumber, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error) +{ + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN; + res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + +int +dwarf_vendor_ext(Dwarf_P_Debug dbg, + Dwarf_Unsigned constant, + char *string, Dwarf_Error * error) +{ + size_t len; + size_t length_est; + int res; + int compose_error_type; + + if (dbg == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); + return (DW_DLV_ERROR); + } + if (string == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); + return (DW_DLV_ERROR); + } + len = strlen(string) + 1; + if (len == 0) { + _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); + return (DW_DLV_ERROR); + } + length_est = COMMAND_LEN + LINE_LEN + len; + res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext, length_est, + &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + res = libdwarf_compose_add_line(dbg, constant, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + libdwarf_compose_add_string(dbg, string, len); + libdwarf_compose_complete(dbg, &compose_error_type); + if (res != DW_DLV_OK) { + _dwarf_p_error(NULL, error, compose_error_type); + return (DW_DLV_ERROR); + } + return DW_DLV_OK; +} + + + +int +_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, + Dwarf_Error * error) +{ + /* Total num of bytes in .debug_macinfo section. */ + Dwarf_Unsigned mac_num_bytes; + + /* Points to first byte of .debug_macinfo buffer. */ + Dwarf_Small *macinfo; + + /* Fills in the .debug_macinfo buffer. */ + Dwarf_Small *macinfo_ptr; + + + /* Used to scan the section data buffers. */ + struct dw_macinfo_block_s *m_prev; + struct dw_macinfo_block_s *m_sect; + + + /* Get the size of the debug_macinfo data */ + mac_num_bytes = 0; + for (m_sect = dbg->de_first_macinfo; m_sect != NULL; + m_sect = m_sect->mb_next) { + mac_num_bytes += m_sect->mb_used_len; + } + /* The final entry has a type code of 0 to indicate It is final + for this CU Takes just 1 byte. */ + mac_num_bytes += 1; + + GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO], + macinfo, (unsigned long) mac_num_bytes, error); + if (macinfo == NULL) { + _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); + return (0); + } + + macinfo_ptr = macinfo; + m_prev = 0; + for (m_sect = dbg->de_first_macinfo; m_sect != NULL; + m_sect = m_sect->mb_next) { + memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len); + macinfo_ptr += m_sect->mb_used_len; + if (m_prev) { + _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); + m_prev = 0; + } + m_prev = m_sect; + } + *macinfo_ptr = 0; /* the type code of 0 as last entry */ + if (m_prev) { + _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); + m_prev = 0; + } + + dbg->de_first_macinfo = NULL; + dbg->de_current_macinfo = NULL; + + return (int) dbg->de_n_debug_sect; +} |