Blame dwarfgen/irepattrtodbg.cc

Packit cdaae3
/*
Packit cdaae3
  Copyright (C) 2010-2013 David Anderson.  All rights reserved.
Packit cdaae3
Packit cdaae3
  Redistribution and use in source and binary forms, with or without
Packit cdaae3
  modification, are permitted provided that the following conditions are met:
Packit cdaae3
  * Redistributions of source code must retain the above copyright
Packit cdaae3
    notice, this list of conditions and the following disclaimer.
Packit cdaae3
  * Redistributions in binary form must reproduce the above copyright
Packit cdaae3
    notice, this list of conditions and the following disclaimer in the
Packit cdaae3
    documentation and/or other materials provided with the distribution.
Packit cdaae3
  * Neither the name of the example nor the
Packit cdaae3
    names of its contributors may be used to endorse or promote products
Packit cdaae3
    derived from this software without specific prior written permission.
Packit cdaae3
Packit cdaae3
  THIS SOFTWARE IS PROVIDED BY David Anderson ''AS IS'' AND ANY
Packit cdaae3
  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit cdaae3
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit cdaae3
  DISCLAIMED. IN NO EVENT SHALL David Anderson BE LIABLE FOR ANY
Packit cdaae3
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit cdaae3
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Packit cdaae3
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Packit cdaae3
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit cdaae3
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit cdaae3
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit cdaae3
Packit cdaae3
*/
Packit cdaae3
Packit cdaae3
// irepattrtodbg.cc
Packit cdaae3
Packit cdaae3
#include "config.h"
Packit cdaae3
Packit cdaae3
/* Windows specific header files */
Packit cdaae3
#ifdef HAVE_STDAFX_H
Packit cdaae3
#include "stdafx.h"
Packit cdaae3
#endif /* HAVE_STDAFX_H */
Packit cdaae3
#if HAVE_UNISTD_H
Packit cdaae3
#include <unistd.h>
Packit cdaae3
#endif
Packit cdaae3
#include <stdlib.h> // for exit
Packit cdaae3
#include <iostream>
Packit cdaae3
#include <sstream> // For BldName
Packit cdaae3
#include <iomanip> // iomanp for setw etc
Packit cdaae3
#include <string>
Packit cdaae3
#include <list>
Packit cdaae3
#include <map>
Packit cdaae3
#include <vector>
Packit cdaae3
#include <string.h> // For memset etc
Packit cdaae3
#include <sys/stat.h> //open
Packit cdaae3
#include <fcntl.h> //open
Packit cdaae3
#include "general.h"
Packit cdaae3
//  gelf.h is a GNU-only elf header. FIXME
Packit cdaae3
#include "gelf.h"
Packit cdaae3
#include "strtabdata.h"
Packit cdaae3
#include "dwarf.h"
Packit cdaae3
#include "libdwarf.h"
Packit cdaae3
#include "irepresentation.h"
Packit cdaae3
#include "ireptodbg.h"
Packit cdaae3
#include "irepattrtodbg.h"
Packit cdaae3
Packit cdaae3
#ifdef HAVE_INTPTR_T
Packit cdaae3
#include <stdint.h>
Packit cdaae3
typedef intptr_t myintfromp; // intptr_t is from C99.
Packit cdaae3
#else
Packit cdaae3
// We want an integer that is big enough for a pointer so the
Packit cdaae3
// pointer return value from the libdwarf producer can be
Packit cdaae3
// tested for -1.  Ugly overloading of integer and pointer in libdwarf.
Packit cdaae3
// We just hope it will compile for you.
Packit cdaae3
typedef long myintfromp;
Packit cdaae3
#endif
Packit cdaae3
Packit cdaae3
using std::string;
Packit cdaae3
using std::cout;
Packit cdaae3
using std::cerr;
Packit cdaae3
using std::endl;
Packit cdaae3
using std::vector;
Packit cdaae3
using std::list;
Packit cdaae3
using std::map;
Packit cdaae3
Packit cdaae3
static Dwarf_Error error;
Packit cdaae3
static unsigned fakeaddrnum;
Packit cdaae3
Packit cdaae3
// We are not going to 'validate' the FORM for this Attribute.
Packit cdaae3
// or this Die.  We just assume that what we are handed is
Packit cdaae3
// what we are to produce.  We do test the attribute
Packit cdaae3
// at times, partly to ensure we use as many of the dwarf_add_AT*
Packit cdaae3
// functions as possible.
Packit cdaae3
Packit cdaae3
// Correctness/appropriateness must be evaluated elsewhere.
Packit cdaae3
Packit cdaae3
void
Packit cdaae3
AddAttrToDie(Dwarf_P_Debug dbg,
Packit cdaae3
    IRepresentation & Irep,
Packit cdaae3
    IRCUdata  &cu,
Packit cdaae3
    Dwarf_P_Die outdie,
Packit cdaae3
    IRDie & irdie,IRAttr &irattr)
Packit cdaae3
{
Packit cdaae3
    int attrnum = irattr.getAttrNum();
Packit cdaae3
    enum Dwarf_Form_Class formclass = irattr.getFormClass();
Packit cdaae3
    // IRForm is an abstract base class.
Packit cdaae3
    IRForm *form = irattr.getFormData();
Packit cdaae3
Packit cdaae3
    switch(formclass) {
Packit cdaae3
    case DW_FORM_CLASS_UNKNOWN:
Packit cdaae3
        cerr << "ERROR AddAttrToDie: Impossible DW_FORM_CLASS_UNKNOWN, attrnum "
Packit cdaae3
            <
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_ADDRESS:
Packit cdaae3
        {
Packit cdaae3
        IRFormAddress *f = dynamic_cast<IRFormAddress *>(form);
Packit cdaae3
        if (!f) {
Packit cdaae3
            cerr << "ERROR Impossible DW_FORM_CLASS_ADDRESS cast fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
        // FIXME: do better creating a symbol:  try to match original
Packit cdaae3
        // or specified input.
Packit cdaae3
        Dwarf_Addr addr = f->getAddress();
Packit cdaae3
Packit cdaae3
        string symname = BldName("addrsym",fakeaddrnum++);
Packit cdaae3
        Dwarf_Addr pcval = addr;
Packit cdaae3
Packit cdaae3
        ElfSymbols& es = Irep.getElfSymbols();
Packit cdaae3
        ElfSymIndex esi = es.addElfSymbol(pcval,symname);
Packit cdaae3
        Dwarf_Unsigned sym_index =  esi.getSymIndex();
Packit cdaae3
Packit cdaae3
        // FIXME: we should  allow for DW_FORM_indirect here.
Packit cdaae3
        // Relocation later will fix value.
Packit cdaae3
        Dwarf_P_Attribute a = dwarf_add_AT_targ_address_b(dbg,
Packit cdaae3
            outdie,attrnum,0,sym_index,&error);
Packit cdaae3
        if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
            cerr << "ERROR dwarf_add_AT_targ_address fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
Packit cdaae3
        }
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_BLOCK:
Packit cdaae3
        {
Packit cdaae3
        //FIXME
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_CONSTANT:
Packit cdaae3
        {
Packit cdaae3
        IRFormConstant *f = dynamic_cast<IRFormConstant *>(form);
Packit cdaae3
        Dwarf_Half form = f->getFinalForm();
Packit cdaae3
        // FIXME: Handle form indirect
Packit cdaae3
        IRFormConstant::Signedness sn = f->getSignedness();
Packit cdaae3
        Dwarf_Unsigned uval = 0;
Packit cdaae3
        Dwarf_P_Attribute a = 0;
Packit cdaae3
Packit cdaae3
        if (form == DW_FORM_data16) {
Packit cdaae3
            Dwarf_Form_Data16 val = f->getData16Val();
Packit cdaae3
            int res = dwarf_add_AT_data16(outdie,
Packit cdaae3
                attrnum,&val,&a,&error);
Packit cdaae3
            if (res != DW_DLV_OK) {
Packit cdaae3
                cerr <<
Packit cdaae3
                "ERROR AddAttrToDie: "
Packit cdaae3
                "dwarf_add_AT_ data16 class constant fails,"
Packit cdaae3
                " attrnum " << attrnum <<
Packit cdaae3
                " res "<
Packit cdaae3
            }
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
        if (sn == IRFormConstant::SIGNED) {
Packit cdaae3
            Dwarf_Signed sval = f->getSignedVal();
Packit cdaae3
            if (form == DW_FORM_sdata) {
Packit cdaae3
                a = dwarf_add_AT_any_value_sleb(
Packit cdaae3
                    outdie,attrnum,
Packit cdaae3
                    sval,&error);
Packit cdaae3
            } else {
Packit cdaae3
                //cerr << "ERROR how can we know "
Packit cdaae3
                //    "a non-sdata const is signed?, attrnum " <<
Packit cdaae3
                //    attrnum <
Packit cdaae3
                a = dwarf_add_AT_signed_const(dbg,
Packit cdaae3
                    outdie,attrnum,
Packit cdaae3
                    sval,&error);
Packit cdaae3
            }
Packit cdaae3
        } else {
Packit cdaae3
            Dwarf_Unsigned uval = f->getUnsignedVal();
Packit cdaae3
            if (form == DW_FORM_udata) {
Packit cdaae3
                a = dwarf_add_AT_any_value_uleb(
Packit cdaae3
                    outdie,attrnum,
Packit cdaae3
                    uval,&error);
Packit cdaae3
            } else {
Packit cdaae3
                a = dwarf_add_AT_unsigned_const(dbg,
Packit cdaae3
                    outdie,attrnum,
Packit cdaae3
                    uval,&error);
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
            cerr << "ERROR dwarf_add_AT_ class constant fails,"
Packit cdaae3
                " BADATTR on attrnum "
Packit cdaae3
                <
Packit cdaae3
Packit cdaae3
        }
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_EXPRLOC:
Packit cdaae3
        {
Packit cdaae3
        //FIXME
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_FLAG:
Packit cdaae3
        {
Packit cdaae3
        IRFormFlag *f = dynamic_cast<IRFormFlag *>(form);
Packit cdaae3
        if (!f) {
Packit cdaae3
            cerr << "ERROR Impossible DW_FORM_CLASS_FLAG cast fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
        // FIXME: handle indirect form (libdwarf needs feature).
Packit cdaae3
        // FIXME: handle implicit flag (libdwarf needs feature).
Packit cdaae3
        // FIXME: rel type ok?
Packit cdaae3
        Dwarf_P_Attribute a =
Packit cdaae3
            dwarf_add_AT_flag(dbg,outdie,attrnum,f->getFlagVal(),&error);
Packit cdaae3
        if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
            cerr << "ERROR dwarf_add_AT_flag fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
        }
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
Packit cdaae3
    case DW_FORM_CLASS_LINEPTR:
Packit cdaae3
        {
Packit cdaae3
        // The DW_AT_stmt_list attribute is generated
Packit cdaae3
        // as a side effect of dwarf_transform_to_disk_form
Packit cdaae3
        // if producer line-info-creating functions were called.
Packit cdaae3
        // So we ignore this attribute here, it is
Packit cdaae3
        // automatic.
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_LOCLISTPTR:
Packit cdaae3
        {
Packit cdaae3
        //FIXME. Needs support in dwarf producer(libdwarf)
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_MACPTR:
Packit cdaae3
        {
Packit cdaae3
        // The DW_AT_macro_info attribute is generated
Packit cdaae3
        // as a side effect of dwarf_transform_to_disk_form
Packit cdaae3
        // if producer macro-creating functions were called.
Packit cdaae3
        // So we ignore this attribute here, it is
Packit cdaae3
        // automatic.
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_RANGELISTPTR:
Packit cdaae3
        {
Packit cdaae3
        //FIXME. Needs support in dwarf producer(libdwarf)
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_REFERENCE:
Packit cdaae3
        {
Packit cdaae3
        // Can be a local CU  reference to a DIE, or a
Packit cdaae3
        // global DIE reference  or a
Packit cdaae3
        // sig8 reference.
Packit cdaae3
        //FIXME
Packit cdaae3
        IRFormReference *r = dynamic_cast<IRFormReference *>(form);
Packit cdaae3
        if (!r) {
Packit cdaae3
            cerr << "ERROR Impossible DW_FORM_CLASS_REFERENCE cast fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        Dwarf_Half finalform = r->getFinalForm();
Packit cdaae3
Packit cdaae3
        IRFormReference::RefType reftype = r->getReferenceType();
Packit cdaae3
        switch (reftype) {
Packit cdaae3
        case IRFormReference::RT_NONE:
Packit cdaae3
            cerr << "ERROR CLASS REFERENCE unknown reftype "
Packit cdaae3
                <
Packit cdaae3
            break;
Packit cdaae3
        case IRFormReference::RT_GLOBAL:
Packit cdaae3
            // FIXME. Not handled.
Packit cdaae3
            break;
Packit cdaae3
        case IRFormReference::RT_CUREL:
Packit cdaae3
            {
Packit cdaae3
            IRDie *targetofref = r->getTargetInDie();
Packit cdaae3
            Dwarf_P_Die targetoutdie = 0;
Packit cdaae3
            if(targetofref) {
Packit cdaae3
                targetoutdie = targetofref->getGeneratedDie();
Packit cdaae3
            }
Packit cdaae3
            if(!targetoutdie) {
Packit cdaae3
                if(!targetofref) {
Packit cdaae3
                    cerr << "ERROR CLASS REFERENCE targetdie of reference unknown"
Packit cdaae3
                        <
Packit cdaae3
                    break;
Packit cdaae3
                }
Packit cdaae3
                // We must add the attribute when we have the
Packit cdaae3
                // target Dwarf_P_Die, which should get set shortly.
Packit cdaae3
                // And do the  dwarf_add_AT_reference() then.
Packit cdaae3
                // Before transform_to_disk_form.
Packit cdaae3
                // NULL targetoutdie allowed here.
Packit cdaae3
                // Arranging DIE order so there were no forward-refs
Packit cdaae3
                // could be difficult.
Packit cdaae3
                // Another option would be two-pass: first create
Packit cdaae3
                // all the DIEs then all the attributes for each.
Packit cdaae3
                Dwarf_P_Attribute a =
Packit cdaae3
                    dwarf_add_AT_reference_b(dbg,outdie,attrnum,
Packit cdaae3
                    /*targetoutdie */NULL,&error);
Packit cdaae3
                if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
                    cerr << "ERROR dwarf_add_AT_reference fails, "
Packit cdaae3
                        "attrnum with not yet known targetoutdie "
Packit cdaae3
                        << IToHex(attrnum) << endl;
Packit cdaae3
                } else {
Packit cdaae3
                    ClassReferenceFixupData x(dbg,attrnum,outdie,targetofref);
Packit cdaae3
                    cu.insertClassReferenceFixupData(x);
Packit cdaae3
                }
Packit cdaae3
                break;
Packit cdaae3
            }
Packit cdaae3
            Dwarf_P_Attribute a =
Packit cdaae3
                dwarf_add_AT_reference(dbg,outdie,attrnum,
Packit cdaae3
                targetoutdie,&error);
Packit cdaae3
            if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
                cerr << "ERROR dwarf_add_AT_reference fails, "
Packit cdaae3
                    "attrnum with known targetoutdie "
Packit cdaae3
                    << IToHex(attrnum) << endl;
Packit cdaae3
            }
Packit cdaae3
            }
Packit cdaae3
            break;
Packit cdaae3
        case IRFormReference::RT_SIG:
Packit cdaae3
            {
Packit cdaae3
            Dwarf_P_Attribute a =
Packit cdaae3
                dwarf_add_AT_with_ref_sig8(outdie,attrnum,
Packit cdaae3
                r->getSignature(),&error);
Packit cdaae3
            if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
                cerr << "ERROR dwarf_add_AT_ref_sig8 fails, attrnum "
Packit cdaae3
                    << IToHex(attrnum) << endl;
Packit cdaae3
            }
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_STRING:
Packit cdaae3
        {
Packit cdaae3
        IRFormString *f = dynamic_cast<IRFormString *>(form);
Packit cdaae3
        if (!f) {
Packit cdaae3
            cerr << "ERROR Impossible DW_FORM_CLASS_STRING cast fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
        Dwarf_P_Attribute a = 0;
Packit cdaae3
        // We know libdwarf does not change the string. Historical mistake
Packit cdaae3
        // not making it a const char * argument.
Packit cdaae3
        // Ugly cast.
Packit cdaae3
        // FIXME: handle indirect form (libdwarf needs feature).
Packit cdaae3
        // FIXME: rel type ok?
Packit cdaae3
        char *mystr = const_cast<char *>(f->getString().c_str());
Packit cdaae3
        switch(attrnum) {
Packit cdaae3
        case DW_AT_name:
Packit cdaae3
            a = dwarf_add_AT_name(outdie,mystr,&error);
Packit cdaae3
            break;
Packit cdaae3
        case DW_AT_producer:
Packit cdaae3
            a = dwarf_add_AT_producer(outdie,mystr,&error);
Packit cdaae3
            break;
Packit cdaae3
        case DW_AT_comp_dir:
Packit cdaae3
            a = dwarf_add_AT_comp_dir(outdie,mystr,&error);
Packit cdaae3
            break;
Packit cdaae3
        default:
Packit cdaae3
            a = dwarf_add_AT_string(dbg,outdie,attrnum,mystr,
Packit cdaae3
                &error);
Packit cdaae3
            break;
Packit cdaae3
        }
Packit cdaae3
        if( reinterpret_cast<myintfromp>(a) == DW_DLV_BADADDR) {
Packit cdaae3
            cerr << "ERROR dwarf_add_AT_string fails, attrnum "
Packit cdaae3
                <
Packit cdaae3
        }
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    case DW_FORM_CLASS_FRAMEPTR: // SGI/MIPS/IRIX only.
Packit cdaae3
        {
Packit cdaae3
        //FIXME
Packit cdaae3
        }
Packit cdaae3
        break;
Packit cdaae3
    default:
Packit cdaae3
        cerr << "ERROR Impossible DW_FORM_CLASS  "<<
Packit cdaae3
            static_cast<int>(formclass)
Packit cdaae3
            <
Packit cdaae3
        //FIXME
Packit cdaae3
    }
Packit cdaae3
    return;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
Packit cdaae3
void
Packit cdaae3
IRCUdata::updateClassReferenceTargets()
Packit cdaae3
{
Packit cdaae3
    for(std::list<ClassReferenceFixupData>::iterator it =
Packit cdaae3
        classReferenceFixupList_.begin();
Packit cdaae3
        it != classReferenceFixupList_.end();
Packit cdaae3
        ++it) {
Packit cdaae3
            IRDie* d = it->target_;
Packit cdaae3
            Dwarf_P_Die sourcedie = it->sourcedie_;
Packit cdaae3
            Dwarf_P_Die targetdie = d->getGeneratedDie();
Packit cdaae3
            Dwarf_Error error = 0;
Packit cdaae3
            int res = dwarf_fixup_AT_reference_die(it->dbg_,
Packit cdaae3
                it->attrnum_,sourcedie,targetdie,&error);
Packit cdaae3
            if(res != DW_DLV_OK) {
Packit cdaae3
                cerr << "Improper dwarf_fixup_AT_reference_die call"
Packit cdaae3
                    << endl;
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
}
Packit cdaae3