Blame libdwarf/pro_line.c

Packit cdaae3
/*
Packit cdaae3
Packit cdaae3
  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
Packit cdaae3
  Portions Copyright 2011-2017 David Anderson. All Rights Reserved.
Packit cdaae3
Packit cdaae3
  This program is free software; you can redistribute it and/or modify it
Packit cdaae3
  under the terms of version 2.1 of the GNU Lesser General Public License
Packit cdaae3
  as published by the Free Software Foundation.
Packit cdaae3
Packit cdaae3
  This program is distributed in the hope that it would be useful, but
Packit cdaae3
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit cdaae3
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit cdaae3
Packit cdaae3
  Further, this software is distributed without any warranty that it is
Packit cdaae3
  free of the rightful claim of any third person regarding infringement
Packit cdaae3
  or the like.  Any license provided herein, whether implied or
Packit cdaae3
  otherwise, applies only to this software file.  Patent licenses, if
Packit cdaae3
  any, provided herein do not apply to combinations of this program with
Packit cdaae3
  other software, or any other product whatsoever.
Packit cdaae3
Packit cdaae3
  You should have received a copy of the GNU Lesser General Public
Packit cdaae3
  License along with this program; if not, write the Free Software
Packit cdaae3
  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
Packit cdaae3
  USA.
Packit cdaae3
Packit cdaae3
*/
Packit cdaae3
Packit cdaae3
#include "config.h"
Packit cdaae3
#include "libdwarfdefs.h"
Packit cdaae3
#include <stdio.h>
Packit cdaae3
#include <string.h>
Packit cdaae3
#ifdef HAVE_ELF_H
Packit cdaae3
#include <elf.h>
Packit cdaae3
#endif
Packit cdaae3
#include "pro_incl.h"
Packit cdaae3
#include "pro_line.h"
Packit cdaae3
Packit cdaae3
static
Packit cdaae3
Dwarf_Unsigned _dwarf_pro_add_line_entry(Dwarf_P_Debug,
Packit cdaae3
    Dwarf_Unsigned file_index,
Packit cdaae3
    Dwarf_Addr code_address,
Packit cdaae3
    Dwarf_Unsigned symidx,
Packit cdaae3
    Dwarf_Unsigned line_no,
Packit cdaae3
    Dwarf_Signed col_no,
Packit cdaae3
    Dwarf_Bool is_stmt_begin,
Packit cdaae3
    Dwarf_Bool is_bb_begin,
Packit cdaae3
    Dwarf_Ubyte opc,
Packit cdaae3
    Dwarf_Bool isepilbeg,
Packit cdaae3
    Dwarf_Bool isprolend,
Packit cdaae3
    Dwarf_Unsigned isa,
Packit cdaae3
    Dwarf_Unsigned discriminator,
Packit cdaae3
    Dwarf_Error * error);
Packit cdaae3
Packit cdaae3
/*  Add a entry to the line information section
Packit cdaae3
    file_index: index of file in file entries, obtained from
Packit cdaae3
    add_file_entry() call.
Packit cdaae3
Packit cdaae3
    This function actually calls _dwarf_pro_add_line_entry(), with
Packit cdaae3
    an extra parameter, the opcode. Done so that interface calls
Packit cdaae3
    dwarf_lne_set_address() and dwarf_lne_end_sequence() can use
Packit cdaae3
    this internal routine. */
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_add_line_entry_b(Dwarf_P_Debug dbg,
Packit cdaae3
    Dwarf_Unsigned file_index,
Packit cdaae3
    Dwarf_Addr     code_address,
Packit cdaae3
    Dwarf_Unsigned line_no,
Packit cdaae3
    Dwarf_Signed   col_no,
Packit cdaae3
    Dwarf_Bool     is_stmt_begin,
Packit cdaae3
    Dwarf_Bool     is_bb_begin,
Packit cdaae3
    Dwarf_Bool     isepilbeg,
Packit cdaae3
    Dwarf_Bool     isprolend,
Packit cdaae3
    Dwarf_Unsigned isa,
Packit cdaae3
    Dwarf_Unsigned discriminator,
Packit cdaae3
    Dwarf_Error *  error)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Unsigned retval = 0;
Packit cdaae3
    Dwarf_Ubyte opc = 0;
Packit cdaae3
    Dwarf_Unsigned symidx = 0;
Packit cdaae3
Packit cdaae3
    retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address,
Packit cdaae3
        symidx,
Packit cdaae3
        line_no, col_no, is_stmt_begin,
Packit cdaae3
        is_bb_begin,
Packit cdaae3
        opc,
Packit cdaae3
        isepilbeg,isprolend,isa,discriminator, error);
Packit cdaae3
    return retval;
Packit cdaae3
}
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_add_line_entry(Dwarf_P_Debug dbg,
Packit cdaae3
    Dwarf_Unsigned file_index,
Packit cdaae3
    Dwarf_Addr code_address,
Packit cdaae3
    Dwarf_Unsigned line_no,
Packit cdaae3
    Dwarf_Signed col_no, /* Wrong, should be unsigned. */
Packit cdaae3
    Dwarf_Bool is_stmt_begin,
Packit cdaae3
    Dwarf_Bool is_bb_begin, Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Unsigned retval = 0;
Packit cdaae3
    Dwarf_Ubyte opc = 0;
Packit cdaae3
    Dwarf_Unsigned symidx = 0;
Packit cdaae3
    Dwarf_Bool isepilbeg = 0;
Packit cdaae3
    Dwarf_Bool isprolend  = 0;
Packit cdaae3
    Dwarf_Unsigned isa = 0;
Packit cdaae3
    Dwarf_Unsigned discriminator = 0;
Packit cdaae3
Packit cdaae3
    retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address,
Packit cdaae3
        symidx,
Packit cdaae3
        line_no, col_no, is_stmt_begin,
Packit cdaae3
        is_bb_begin,
Packit cdaae3
        opc,
Packit cdaae3
        isepilbeg, isprolend, isa, discriminator,
Packit cdaae3
        error);
Packit cdaae3
    return retval;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
void
Packit cdaae3
_dwarf_init_default_line_header_vals(Dwarf_P_Debug dbg)
Packit cdaae3
{
Packit cdaae3
    dbg->de_line_inits.pi_version = dbg->de_output_version;
Packit cdaae3
Packit cdaae3
    dbg->de_line_inits.pi_default_is_stmt = DEFAULT_IS_STMT;
Packit cdaae3
    dbg->de_line_inits.pi_minimum_instruction_length = MIN_INST_LENGTH;
Packit cdaae3
    dbg->de_line_inits.pi_maximum_operations_per_instruction = 1;
Packit cdaae3
    dbg->de_line_inits.pi_opcode_base = OPCODE_BASE;
Packit cdaae3
    dbg->de_line_inits.pi_line_base = LINE_BASE;
Packit cdaae3
    dbg->de_line_inits.pi_line_range = LINE_RANGE;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
Packit cdaae3
/*  Ask to emit DW_LNE_set_address opcode explicitly. Used by be
Packit cdaae3
    to emit start of a new .text section, or to force a relocated
Packit cdaae3
    address into debug line information entry. */
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_lne_set_address(Dwarf_P_Debug dbg,
Packit cdaae3
    Dwarf_Addr offs,
Packit cdaae3
    Dwarf_Unsigned symidx, Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Ubyte    opc = 0;
Packit cdaae3
    Dwarf_Unsigned retval = 0;
Packit cdaae3
    Dwarf_Unsigned file_index = 0;
Packit cdaae3
    Dwarf_Unsigned line_no = 0;
Packit cdaae3
    Dwarf_Signed   col_no = 0;
Packit cdaae3
    Dwarf_Bool     is_stmt = 0;
Packit cdaae3
    Dwarf_Bool     is_bb = 0;
Packit cdaae3
    Dwarf_Bool     isepilbeg = 0;
Packit cdaae3
    Dwarf_Bool     isprolend  = 0;
Packit cdaae3
    Dwarf_Unsigned isa = 0;
Packit cdaae3
    Dwarf_Unsigned discriminator = 0;
Packit cdaae3
Packit cdaae3
Packit cdaae3
    opc = DW_LNE_set_address;
Packit cdaae3
    retval =
Packit cdaae3
        _dwarf_pro_add_line_entry(dbg, file_index, offs,
Packit cdaae3
            symidx,
Packit cdaae3
            line_no, col_no, is_stmt,
Packit cdaae3
            is_bb,
Packit cdaae3
            opc,
Packit cdaae3
            isepilbeg, isprolend, isa, discriminator,
Packit cdaae3
            error);
Packit cdaae3
    return retval;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  Ask to emit end_seqence opcode. Used normally at the end of a
Packit cdaae3
    compilation unit. Can also be used in the middle if there
Packit cdaae3
    are gaps in the region described by the code address.  */
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_lne_end_sequence(Dwarf_P_Debug dbg,
Packit cdaae3
    Dwarf_Addr end_address, Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    Dwarf_Ubyte    opc = 0;
Packit cdaae3
    Dwarf_Unsigned retval = 0;
Packit cdaae3
    Dwarf_Unsigned file_index = 0;
Packit cdaae3
    Dwarf_Unsigned symidx = 0;
Packit cdaae3
    Dwarf_Unsigned line_no = 0;
Packit cdaae3
    Dwarf_Bool     is_stmt = 0;
Packit cdaae3
    Dwarf_Bool     is_bb = 0;
Packit cdaae3
    Dwarf_Signed   col_no = 0;/* Wrong, should be unsigned. */
Packit cdaae3
    Dwarf_Bool     isepilbeg = 0;
Packit cdaae3
    Dwarf_Bool     isprolend  = 0;
Packit cdaae3
    Dwarf_Unsigned isa = 0;
Packit cdaae3
    Dwarf_Unsigned discriminator = 0;
Packit cdaae3
Packit cdaae3
    opc = DW_LNE_end_sequence;
Packit cdaae3
    retval =
Packit cdaae3
        _dwarf_pro_add_line_entry(dbg, file_index, end_address,
Packit cdaae3
            symidx,
Packit cdaae3
            line_no, col_no, is_stmt,
Packit cdaae3
            is_bb,
Packit cdaae3
            opc,
Packit cdaae3
            isepilbeg, isprolend, isa, discriminator,
Packit cdaae3
            error);
Packit cdaae3
    return retval;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  Add an entry in the internal list of lines mantained by producer.
Packit cdaae3
    Opc indicates if an opcode needs to be generated, rather than just
Packit cdaae3
    an entry in the matrix. During opcodes generation time, these
Packit cdaae3
    opcodes will be used. */
Packit cdaae3
static Dwarf_Unsigned
Packit cdaae3
_dwarf_pro_add_line_entry(Dwarf_P_Debug dbg,
Packit cdaae3
    Dwarf_Unsigned file_index,
Packit cdaae3
    Dwarf_Addr code_address,
Packit cdaae3
    Dwarf_Unsigned symidx,
Packit cdaae3
    Dwarf_Unsigned line_no,
Packit cdaae3
    Dwarf_Signed col_no,
Packit cdaae3
    Dwarf_Bool is_stmt_begin,
Packit cdaae3
    Dwarf_Bool is_bb_begin,
Packit cdaae3
    Dwarf_Ubyte opc,
Packit cdaae3
    Dwarf_Bool isepilbeg,
Packit cdaae3
    Dwarf_Bool isprolend,
Packit cdaae3
    Dwarf_Unsigned isa,
Packit cdaae3
    Dwarf_Unsigned discriminator,
Packit cdaae3
    Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    if (dbg->de_lines == NULL) {
Packit cdaae3
        dbg->de_lines = (Dwarf_P_Line)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
Packit cdaae3
        if (dbg->de_lines == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        dbg->de_last_line = dbg->de_lines;
Packit cdaae3
        _dwarf_pro_reg_init(dbg,dbg->de_lines);
Packit cdaae3
Packit cdaae3
    } else {
Packit cdaae3
        dbg->de_last_line->dpl_next = (Dwarf_P_Line)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
Packit cdaae3
        if (dbg->de_last_line->dpl_next == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        dbg->de_last_line = dbg->de_last_line->dpl_next;
Packit cdaae3
        _dwarf_pro_reg_init(dbg,dbg->de_last_line);
Packit cdaae3
    }
Packit cdaae3
    dbg->de_last_line->dpl_address = code_address;
Packit cdaae3
    dbg->de_last_line->dpl_file = (unsigned long) file_index;
Packit cdaae3
    dbg->de_last_line->dpl_line = (unsigned long) line_no;
Packit cdaae3
    dbg->de_last_line->dpl_column = (unsigned long) col_no;
Packit cdaae3
    dbg->de_last_line->dpl_is_stmt = is_stmt_begin;
Packit cdaae3
    dbg->de_last_line->dpl_basic_block = is_bb_begin;
Packit cdaae3
    dbg->de_last_line->dpl_opc = opc;
Packit cdaae3
    dbg->de_last_line->dpl_r_symidx = symidx;
Packit cdaae3
    dbg->de_last_line->dpl_prologue_end = isprolend;
Packit cdaae3
    dbg->de_last_line->dpl_epilogue_begin = isepilbeg;
Packit cdaae3
    dbg->de_last_line->dpl_isa = isa;
Packit cdaae3
    dbg->de_last_line->dpl_discriminator = discriminator;
Packit cdaae3
    return (0);
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  Add a directory declaration to the debug_line section. Stored
Packit cdaae3
    in linked list. */
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_add_directory_decl(Dwarf_P_Debug dbg,
Packit cdaae3
    char *name, Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    if (dbg->de_inc_dirs == NULL) {
Packit cdaae3
        dbg->de_inc_dirs = (Dwarf_P_F_Entry)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
Packit cdaae3
        if (dbg->de_inc_dirs == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        dbg->de_last_inc_dir = dbg->de_inc_dirs;
Packit cdaae3
        dbg->de_n_inc_dirs = 1;
Packit cdaae3
    } else {
Packit cdaae3
        dbg->de_last_inc_dir->dfe_next = (Dwarf_P_F_Entry)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
Packit cdaae3
        if (dbg->de_last_inc_dir->dfe_next == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        dbg->de_last_inc_dir = dbg->de_last_inc_dir->dfe_next;
Packit cdaae3
        dbg->de_n_inc_dirs++;
Packit cdaae3
    }
Packit cdaae3
    dbg->de_last_inc_dir->dfe_name =
Packit cdaae3
        (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
Packit cdaae3
    if (dbg->de_last_inc_dir->dfe_name == NULL) {
Packit cdaae3
        DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_NOCOUNT);
Packit cdaae3
    }
Packit cdaae3
    strcpy(dbg->de_last_inc_dir->dfe_name, name);
Packit cdaae3
    dbg->de_last_inc_dir->dfe_next = NULL;
Packit cdaae3
Packit cdaae3
    return dbg->de_n_inc_dirs;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  Add a file entry declaration to the debug_line section. Stored
Packit cdaae3
    in linked list. The data is immediately encoded as leb128
Packit cdaae3
    and stored in Dwarf_P_F_Entry_s struct. */
Packit cdaae3
Dwarf_Unsigned
Packit cdaae3
dwarf_add_file_decl(Dwarf_P_Debug dbg,
Packit cdaae3
    char *name,
Packit cdaae3
    Dwarf_Unsigned dir_idx,
Packit cdaae3
    Dwarf_Unsigned time_mod,
Packit cdaae3
    Dwarf_Unsigned length, Dwarf_Error * error)
Packit cdaae3
{
Packit cdaae3
    Dwarf_P_F_Entry cur;
Packit cdaae3
    char *ptr = 0;
Packit cdaae3
    int nbytes_idx, nbytes_time, nbytes_len;
Packit cdaae3
    char buffidx[ENCODE_SPACE_NEEDED];
Packit cdaae3
    char bufftime[ENCODE_SPACE_NEEDED];
Packit cdaae3
    char bufflen[ENCODE_SPACE_NEEDED];
Packit cdaae3
    int res = 0;
Packit cdaae3
Packit cdaae3
    if (dbg->de_file_entries == NULL) {
Packit cdaae3
        dbg->de_file_entries = (Dwarf_P_F_Entry)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
Packit cdaae3
        if (dbg->de_file_entries == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
Packit cdaae3
                DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        cur = dbg->de_file_entries;
Packit cdaae3
        dbg->de_last_file_entry = cur;
Packit cdaae3
        dbg->de_n_file_entries = 1;
Packit cdaae3
    } else {
Packit cdaae3
        cur = dbg->de_last_file_entry;
Packit cdaae3
        cur->dfe_next = (Dwarf_P_F_Entry)
Packit cdaae3
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
Packit cdaae3
        if (cur->dfe_next == NULL) {
Packit cdaae3
            DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
Packit cdaae3
                DW_DLV_NOCOUNT);
Packit cdaae3
        }
Packit cdaae3
        cur = cur->dfe_next;
Packit cdaae3
        dbg->de_last_file_entry = cur;
Packit cdaae3
        dbg->de_n_file_entries++;
Packit cdaae3
    }
Packit cdaae3
    cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
Packit cdaae3
    if (cur->dfe_name == NULL) {
Packit cdaae3
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
Packit cdaae3
    }
Packit cdaae3
    strcpy((char *) cur->dfe_name, name);
Packit cdaae3
    res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx,
Packit cdaae3
        buffidx, sizeof(buffidx));
Packit cdaae3
    if (res != DW_DLV_OK) {
Packit cdaae3
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
Packit cdaae3
    }
Packit cdaae3
    res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time,
Packit cdaae3
        bufftime, sizeof(bufftime));
Packit cdaae3
    if (res != DW_DLV_OK) {
Packit cdaae3
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
Packit cdaae3
    }
Packit cdaae3
    res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len,
Packit cdaae3
        bufflen, sizeof(bufflen));
Packit cdaae3
    cur->dfe_args = (char *)
Packit cdaae3
        _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len);
Packit cdaae3
    if (cur->dfe_args == NULL) {
Packit cdaae3
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
Packit cdaae3
    }
Packit cdaae3
    ptr = cur->dfe_args;
Packit cdaae3
    memcpy((void *) ptr, buffidx, nbytes_idx);
Packit cdaae3
    ptr += nbytes_idx;
Packit cdaae3
    memcpy((void *) ptr, bufftime, nbytes_time);
Packit cdaae3
    ptr += nbytes_time;
Packit cdaae3
    memcpy((void *) ptr, bufflen, nbytes_len);
Packit cdaae3
    ptr += nbytes_len;
Packit cdaae3
    cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len;
Packit cdaae3
    cur->dfe_next = NULL;
Packit cdaae3
Packit cdaae3
    return dbg->de_n_file_entries;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
Packit cdaae3
/*  Initialize a row of the matrix for line numbers, meaning
Packit cdaae3
    initialize the struct corresponding to it */
Packit cdaae3
void
Packit cdaae3
_dwarf_pro_reg_init(Dwarf_P_Debug dbg, Dwarf_P_Line cur_line)
Packit cdaae3
{
Packit cdaae3
    cur_line->dpl_address = 0;
Packit cdaae3
    cur_line->dpl_file = 1;
Packit cdaae3
    cur_line->dpl_line = 1;
Packit cdaae3
    cur_line->dpl_column = 0;
Packit cdaae3
    cur_line->dpl_is_stmt = dbg->de_line_inits.pi_default_is_stmt;
Packit cdaae3
    cur_line->dpl_basic_block = false;
Packit cdaae3
    cur_line->dpl_next = NULL;
Packit cdaae3
    cur_line->dpl_prologue_end = 0;
Packit cdaae3
    cur_line->dpl_epilogue_begin = 0;
Packit cdaae3
    cur_line->dpl_isa = 0;
Packit cdaae3
    cur_line->dpl_discriminator = 0;
Packit cdaae3
    cur_line->dpl_opc = 0;
Packit cdaae3
}