summaryrefslogtreecommitdiff
path: root/libdwarf/pro_macinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwarf/pro_macinfo.c')
-rw-r--r--libdwarf/pro_macinfo.c468
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;
+}