dbgdwarf.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 880 行 · 第 1/3 页

C
880
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Routines for producing DWARF debugging information.
*
****************************************************************************/


#include <string.h>
#include <setjmp.h>
#include "walloca.h"
#include "linkstd.h"
#include "alloc.h"
#include "objcalc.h"
#include "ring.h"
#include "exeelf.h"
#include "strtab.h"
#include "tistrail.h"
#include "dwarf.h"
#include "dw.h"
#include "dwutils.h"
#include "loadfile.h"
#include "virtmem.h"
#include "objnode.h"
#include "dbgcomm.h"
#include "dbgdwarf.h"
#include "fileio.h"
#include "loadelf.h"
#include "specials.h"

static class_entry *    DBIClass;       // Assume there is only one!

typedef struct {
    virt_mem    addr;
    unsigned_32 size;
} dwarfsect;

typedef struct dwarfmodinfo {
    dwarfsect   pubsym;
    dwarfsect   dasi;
    dwarfsect   arange;
} dwarfmodinfo;

// this used to hold information about linker generated debugging information.

typedef struct {
    virt_mem    addr;   // virt. mem. block containing genned info.
    unsigned_32 size;   // size of linker generated info.
    unsigned_32 start;  // start of linker generated info - compiler stuff 1st
    char *      name;
} sectioninfo;

static sectioninfo SectionTable[] = {
    { 0, 0, 0, ".debug_info" },
    { 0, 0, 0, ".debug_abbrev" },
    { 0, 0, 0, ".debug_line" },
    { 0, 0, 0, ".debug_aranges" }
};

enum {
    SECT_DEBUG_INFO,    // assumed to be in the same order as segment flags!
    SECT_DEBUG_ABBREV,
    SECT_DEBUG_LINE,
    SECT_DEBUG_ARANGE,
    SECT_NUM_SECTIONS
};

#pragma pack( 1 )

// die information

typedef struct {
    unsigned_8  abbrev_code;    // the abbrev code used.
//  unsigned_32 stmt_list;      // (optional) offset to the line number info
//    char      name[1];        // name of the module
} compunit_die;

typedef struct {
    unsigned_8  abbrev_code;
    offset      off;
    unsigned_8  isexternal;
//    char      name[1];
} symbol_die;

typedef struct {
    unsigned_8  len;
    unsigned_8  loc_op;
    unsigned_16 seg;
} symbol_seg;

// the abbrev codes used in the linker's autogenned stuff.


#define NULL_ABBREV_CODE        0
#define COMPUNIT_ABBREV_CODE    1
#define CU_NOLINE_ABBREV_CODE   2
#define LABEL_ABBREV_CODE       3
#define VARIABLE_ABBREV_CODE    4
#define LAST_ABBREV_CODE        4

#if LAST_ABBREV_CODE != LAST_LINKER_ABBREV
#error "make sure dwarf.h is updated and dwarf writing library recompiled!"
#endif

static char SegmentedStandardAbbrevs[] = {
    COMPUNIT_ABBREV_CODE,
    DW_TAG_compile_unit,
    DW_CHILDREN_yes,
    DW_AT_stmt_list,    DW_FORM_ref_addr,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    CU_NOLINE_ABBREV_CODE,
    DW_TAG_compile_unit,
    DW_CHILDREN_yes,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    LABEL_ABBREV_CODE,
    DW_TAG_label,
    DW_CHILDREN_no,
    DW_AT_low_pc,       DW_FORM_addr,
    DW_AT_external,     DW_FORM_flag,
    DW_AT_segment,      DW_FORM_block1,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    VARIABLE_ABBREV_CODE,
    DW_TAG_variable,
    DW_CHILDREN_no,
    DW_AT_low_pc,       DW_FORM_addr,
    DW_AT_external,     DW_FORM_flag,
    DW_AT_segment,      DW_FORM_block1,
    DW_AT_name,         DW_FORM_string,
    0,                  0
};

static char FlatStandardAbbrevs[] = {
    COMPUNIT_ABBREV_CODE,
    DW_TAG_compile_unit,
    DW_CHILDREN_yes,
    DW_AT_stmt_list,    DW_FORM_ref_addr,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    CU_NOLINE_ABBREV_CODE,
    DW_TAG_compile_unit,
    DW_CHILDREN_yes,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    LABEL_ABBREV_CODE,
    DW_TAG_label,
    DW_CHILDREN_no,
    DW_AT_low_pc,       DW_FORM_addr,
    DW_AT_external,     DW_FORM_flag,
    DW_AT_name,         DW_FORM_string,
    0,                  0,
    VARIABLE_ABBREV_CODE,
    DW_TAG_variable,
    DW_CHILDREN_no,
    DW_AT_low_pc,       DW_FORM_addr,
    DW_AT_external,     DW_FORM_flag,
    DW_AT_name,         DW_FORM_string,
    0,                  0
};
#pragma pack()

static void DwarfAddLines( segdata *, void *, unsigned, bool );

extern void DwarfInit( void )
/***************************/
{
    int index;

    DBIClass = NULL;
    for( index = 0; index < SECT_NUM_SECTIONS; index++ ) {
        SectionTable[index].addr = 0;
        SectionTable[index].size = 0;
        SectionTable[index].start = 0;
    }
}

extern void DwarfInitModule( mod_entry *mod )
/*******************************************/
{
    _PermAlloc( mod->d.d, sizeof( dwarfmodinfo ) );
    memset( mod->d.d, 0, sizeof( dwarfmodinfo ) );
}

extern void DwarfP1ModuleScanned( void )
/**************************************/
{
}

extern void DwarfP1ModuleFinished( mod_entry *mod )
/*************************************************/
{
    if( MOD_NOT_DEBUGGABLE( mod ) )
        return;
    CurrMod = mod;
    if( mod->modinfo & MOD_DBI_SEEN )
        return;
    DBILineWalk( mod->lines, DwarfAddLines );
    Ring2Walk( mod->publist, DBIModGlobal );
    if( FmtData.type & MK_SEGMENTED ) {
        SectionTable[SECT_DEBUG_ABBREV].size = sizeof( SegmentedStandardAbbrevs );
    } else {
        SectionTable[SECT_DEBUG_ABBREV].size = sizeof( FlatStandardAbbrevs );
    }
    if( mod->d.d->dasi.size > 0 ) {
        mod->d.d->dasi.addr = SectionTable[SECT_DEBUG_LINE].size;
        mod->d.d->dasi.size += strlen( mod->name ) + sizeof( stmt_prologue ) + 6;
        SectionTable[SECT_DEBUG_LINE].size += mod->d.d->dasi.size;
        mod->d.d->pubsym.size += sizeof( unsigned_32 ); // DW_AT_STMT_LIST
    }
    mod->d.d->pubsym.addr = SectionTable[SECT_DEBUG_INFO].size;
    mod->d.d->pubsym.size += strlen( mod->name ) + sizeof( compunit_die ) + 1
                             + COMPILE_UNIT_HDR_SIZE + 1;
    SectionTable[SECT_DEBUG_INFO].size += mod->d.d->pubsym.size;
}

extern void DwarfStoreAddrInfo( mod_entry *mod )
/**********************************************/
{
    if( !( mod->modinfo & MOD_DBI_SEEN ) ) {
        if( mod->d.d->arange.size > 0 ) {
            mod->d.d->arange.addr = SectionTable[SECT_DEBUG_ARANGE].size;
            mod->d.d->arange.size += sizeof( arange_prologue );
            if( FmtData.type & MK_SEGMENTED ) {
                mod->d.d->arange.size += sizeof( segmented_arange_tuple );
            } else {
                mod->d.d->arange.size += sizeof( flat_arange_tuple );
            }
            SectionTable[SECT_DEBUG_ARANGE].size += mod->d.d->arange.size;
        }
    }
}

extern void DwarfAddModule( mod_entry *mod, section *sect )
/*********************************************************/
// this generates the headers needed in the individual sections
{
    arange_prologue     arange_hdr;
    stmt_prologue       stmt_hdr;
    compuhdr_prologue   compuhdr;
    compunit_die        die;
    size_t              namelen;
    char *              buff;
    unsigned_32         stmt_list;

    sect = sect;
    if( !( mod->modinfo & MOD_DBI_SEEN ) ) {
        namelen = strlen( mod->name );
        if( mod->d.d->arange.size > 0 ) {
            mod->d.d->arange.addr += SectionTable[SECT_DEBUG_ARANGE].addr;
            arange_hdr.length = mod->d.d->arange.size - sizeof( unsigned_32 );
            arange_hdr.version = 2;
            arange_hdr.debug_offset = mod->d.d->pubsym.addr
                                      + SectionTable[SECT_DEBUG_INFO].start;
            arange_hdr.offset_size = sizeof( offset );
            if( FmtData.type & MK_SEGMENTED ) {
                arange_hdr.segment_size = sizeof( segment );
            } else {
                arange_hdr.segment_size = 0;
            }
//          memset( arange_hdr.padding, 0, sizeof( arange_hdr.padding ) );
            PutInfo( mod->d.d->arange.addr, (void *)&arange_hdr,
                     sizeof( arange_prologue ) );
            mod->d.d->arange.addr += sizeof( arange_prologue );
        }
        mod->d.d->pubsym.addr += SectionTable[SECT_DEBUG_INFO].addr;
        compuhdr.length = mod->d.d->pubsym.size - sizeof( unsigned_32 );
        compuhdr.version = 2;
        compuhdr.abbrev_offset = SectionTable[SECT_DEBUG_ABBREV].start;
        compuhdr.addr_size = sizeof( offset );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?