Skip to main content
summaryrefslogblamecommitdiffstats
blob: 48dee5787c6e136ac4622470db1de77ec757a032 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                
                                                                






                                                                           
                                                                          







                                                                                 
 
                   
 
                                     


                   
                             







                                 
                        
 






                                
                      

                                     
                                     








































                                                                    
 
                                                             
                             

                                                                                      


                













                                                            




                                                 


                                                                                               
                

 

                             







                                                                                     
                                          
                                                    


                                            


                                                                                                               









                                                         
                                      
                          
     
 





                                                                                            
                                                                             



                                     
                                               











                                                                                                        
                                                            
 
 


                                                                                 
 


                           


                                                           
                                                           
























                                                                                              
                      
                                                        
                                

 
                                     
                

                    
                                                 
                                                                   
                            
 
                                              
                                                                                             

                                                                                                             
                      
                        
                                                                                              
                                                                                                                
                                                             
              



                                          

                                                
                               




                                            
                                             

                                                                       

                                     
                                                                                                                          
                                                   
                                                                
                                              
                                  
                                                                 
                       




                           
                                                                                     

 
                                                                     
                         


                                            
                        





                                                
                                  

                                                           
                             






                                                                          
     
                                                                                   

                                                                           


                                                                                                 

          
                                                                                

     

















                                                    
                                                      
     
 


                                                                       

 
                                              
/*******************************************************************************
 * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 * The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 * You may elect to redistribute this code under either of these licenses.
 *
 * Contributors:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/

/*
 * This module implements DWARF expressions evaluation.
 */

#include <config.h>

#if ENABLE_ELF && ENABLE_DebugContext

#include <assert.h>
#include <stdio.h>
#include <framework/events.h>
#include <framework/myalloc.h>
#include <framework/exceptions.h>
#include <framework/errors.h>
#include <framework/trace.h>
#include <services/dwarf.h>
#include <services/dwarfio.h>
#include <services/dwarfexpr.h>
#include <services/stacktrace.h>
#include <services/vm.h>

typedef struct ValuePieces {
    U4_T mCnt;
    U4_T mMax;
    PropertyValuePiece * mArray;
    struct ValuePieces * mNext;
} ValuePieces;

static VMState sState;
static ELF_Section * sSection = NULL;
static U8_T sSectionOffs = 0;
static PropertyValue * sValue = NULL;
static ValuePieces * sValuePieces = NULL;

static ValuePieces * sFreeValuePieces = NULL;
static ValuePieces * sBusyValuePieces = NULL;
static unsigned sValuePiecesCnt = 0;
static int sValuePiecesPosted = 0;

static void free_value_pieces(void * args) {
    while (sBusyValuePieces != NULL) {
        ValuePieces * Pieces = sBusyValuePieces;
        sBusyValuePieces = Pieces->mNext;
        Pieces->mNext = sFreeValuePieces;
        sFreeValuePieces = Pieces;
    }
    while (sFreeValuePieces != NULL && sValuePiecesCnt > 16) {
        ValuePieces * Pieces = sFreeValuePieces;
        sFreeValuePieces = sFreeValuePieces->mNext;
        sValuePiecesCnt--;
        loc_free(Pieces->mArray);
        loc_free(Pieces);
    }
}

static ValuePieces * alloc_value_pieces(void) {
    ValuePieces * Pieces = sFreeValuePieces;
    if (Pieces == NULL) {
        Pieces = (ValuePieces *)loc_alloc_zero(sizeof(ValuePieces));
        sValuePiecesCnt++;
    }
    else {
        sFreeValuePieces = sFreeValuePieces->mNext;
    }
    Pieces->mNext = sBusyValuePieces;
    sBusyValuePieces = Pieces;
    if (!sValuePiecesPosted && sValuePiecesCnt > 8) {
        post_event(free_value_pieces, NULL);
        sValuePiecesPosted = 1;
    }
    Pieces->mCnt = 0;
    return Pieces;
}

static StackFrame * get_stack_frame(PropertyValue * sValue) {
    StackFrame * Info = NULL;
    if (sValue->mFrame == STACK_NO_FRAME) return NULL;
    if (get_frame_info(sValue->mContext, sValue->mFrame, &Info) < 0) exception(errno);
    return Info;
}

static ObjectInfo * get_parent_function(ObjectInfo * Info) {
    while (Info != NULL) {
        switch (Info->mTag) {
        case TAG_global_subroutine:
        case TAG_subroutine:
        case TAG_subprogram:
        case TAG_entry_point:
            return Info;
        }
        Info = Info->mParent;
    }
    return NULL;
}

static U8_T read_address(void) {
    U8_T addr = 0;
    ELF_Section * section = NULL;
    CompUnit * Unit = sValue->mObject->mCompUnit;

    addr = dio_ReadAddress(&section);
    addr = elf_map_to_run_time_address(sState.ctx, Unit->mFile, section, (ContextAddress)addr);
    if (addr == 0) str_exception(ERR_INV_ADDRESS, "Object has no RT address");
    return addr;
}

static U8_T get_fbreg(void) {
    PropertyValue FP;
    CompUnit * Unit = sValue->mObject->mCompUnit;
    ObjectInfo * Parent = get_parent_function(sValue->mObject);
    U8_T addr = 0;

    if (Parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function");
    memset(&FP, 0, sizeof(FP));

    {
        PropertyValue * OrgValue = sValue;
        ValuePieces * OrgValuePieces = sValuePieces;
        ELF_Section * OrgSection = sSection;
        U8_T OrgSectionOffs = sSectionOffs;
        VMState OrgState = sState;

        read_and_evaluate_dwarf_object_property(sState.ctx, sState.stack_frame, 0, Parent, AT_frame_base, &FP);

        assert(sState.ctx == OrgState.ctx);
        assert(sState.addr_size == OrgState.addr_size);
        assert(sState.big_endian == OrgState.big_endian);

        sState.code = OrgState.code;
        sState.code_pos = OrgState.code_pos;
        sState.code_len = OrgState.code_len;
        sState.object_address = OrgState.object_address;
        sSectionOffs = OrgSectionOffs;
        sSection = OrgSection;
        sValuePieces = OrgValuePieces;
        sValue = OrgValue;
    }

    if (FP.mRegister != NULL) {
        if (read_reg_value(get_stack_frame(&FP), FP.mRegister, &addr) < 0) exception(errno);
    }
    else {
        addr = get_numeric_property_value(&FP);
    }
    dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs + sState.code_pos);
    return addr + dio_ReadS8LEB128();
}

static void client_op(uint8_t op) {
    dio_SetPos(sSectionOffs + sState.code_pos);
    switch (op) {
    case OP_addr:
        sState.stk[sState.stk_pos++] = read_address();
        break;
    case OP_fbreg:
        if (sState.stack_frame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
        sState.stk[sState.stk_pos++] = get_fbreg();
        break;
    default:
        trace(LOG_ALWAYS, "Unsupported DWARF expression op 0x%02x", op);
        str_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op");
    }
    sState.code_pos = (size_t)(dio_GetPos() - sSectionOffs);
}

static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) {
    int error = 0;
    CompUnit * Unit = sValue->mObject->mCompUnit;

    sState.code = Buf;
    sState.code_len = Size;
    sState.code_pos = 0;
    sSection = Section;
    sSectionOffs = Buf - (U1_T *)Section->data;
    dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs);
    if (evaluate_vm_expression(&sState) < 0) error = errno;
    if (!error && sState.piece_bits) {
        sValuePieces = alloc_value_pieces();
        while (!error) {
            PropertyValuePiece * Piece;
            if (sValuePieces->mCnt >= sValuePieces->mMax) {
                sValuePieces->mMax += 8;
                sValuePieces->mArray = (PropertyValuePiece *)loc_realloc(sValuePieces->mArray,
                    sizeof(PropertyValuePiece) * sValuePieces->mMax);
            }
            Piece = sValuePieces->mArray + sValuePieces->mCnt++;
            memset(Piece, 0, sizeof(PropertyValuePiece));
            if (sState.reg) {
                Piece->mRegister = sState.reg;
                Piece->mBigEndian = sState.reg->big_endian;
            }
            else {
                Piece->mAddress = sState.stk[--sState.stk_pos];
                Piece->mBigEndian = sState.big_endian;
            }
            Piece->mBitOffset = sState.piece_offs;
            Piece->mBitSize = sState.piece_bits;
            if (sState.code_pos >= sState.code_len) break;
            if (evaluate_vm_expression(&sState) < 0) error = errno;
        }
    }
    dio_ExitSection();
    assert(error || sState.code_pos == sState.code_len);
    if (error) exception(error);
}

static void evaluate_location(void) {
    U8_T IP = 0;
    U8_T Offset = 0;
    U8_T Base = 0;
    CompUnit * Unit = sValue->mObject->mCompUnit;
    DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
    U8_T AddrMax = ~(U8_T)0;

    assert(Cache->magic == DWARF_CACHE_MAGIC);
    if (Cache->mDebugLoc == NULL) str_exception(ERR_INV_DWARF, "Missing .debug_loc section");
    dio_EnterSection(&Unit->mDesc, Unit->mDesc.mSection, sValue->mAddr - (U1_T *)Unit->mDesc.mSection->data);
    Offset = dio_ReadUX(sValue->mSize);
    dio_ExitSection();
    Base = Unit->mLowPC;
    if (Unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << Unit->mDesc.mAddressSize * 8) - 1;
    if (read_reg_value(get_stack_frame(sValue), get_PC_definition(sValue->mContext), &IP) < 0) exception(errno);
    dio_EnterSection(&Unit->mDesc, Cache->mDebugLoc, Offset);
    for (;;) {
        ELF_Section * S0 = NULL;
        ELF_Section * S1 = NULL;
        U8_T Addr0 = dio_ReadAddress(&S0);
        U8_T Addr1 = dio_ReadAddress(&S1);
        if (S0 == NULL) S0 = Unit->mTextSection;
        if (S1 == NULL) S1 = Unit->mTextSection;
        if (Addr0 == AddrMax) {
            Base = Addr1;
        }
        else if (Addr0 == 0 && Addr1 == 0) {
            break;
        }
        else if (S0 != S1 || Addr0 > Addr1) {
            str_exception(ERR_INV_DWARF, "Invalid .debug_loc section");
        }
        else {
            U2_T Size = dio_ReadU2();
            U8_T RTAddr0 = elf_map_to_run_time_address(sValue->mContext, Unit->mFile, S0, (ContextAddress)(Base + Addr0));
            U8_T RTAddr1 = Addr1 - Addr0 + RTAddr0;
            if (RTAddr0 != 0 && IP >= RTAddr0 && IP < RTAddr1) {
                U1_T * Buf = dio_GetDataPtr();
                dio_ExitSection();
                evaluate_expression(Cache->mDebugLoc, Buf, Size);
                return;
            }
            dio_Skip(Size);
        }
    }
    dio_ExitSection();
    str_exception(ERR_OTHER, "Object is not available at this location in the code");
}

void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) {
    unsigned stk_pos = 0;
    CompUnit * Unit = v->mObject->mCompUnit;

    sValue = v;
    sValuePieces = NULL;
    sState.ctx = sValue->mContext;
    sState.addr_size = Unit->mDesc.mAddressSize;
    sState.big_endian = Unit->mFile->big_endian;
    sState.stack_frame = sValue->mFrame;
    sState.reg_id_scope = Unit->mRegIdScope;
    sState.object_address = BaseAddress;
    sState.client_op = client_op;;

    if (sValue->mAttr != AT_frame_base) sState.stk_pos = 0;
    stk_pos = sState.stk_pos;

    if (sValue->mAttr == AT_data_member_location) {
        if (sState.stk_pos >= sState.stk_max) {
            sState.stk_max += 8;
            sState.stk = (U8_T *)loc_alloc(sizeof(U8_T) * sState.stk_max);
        }
        sState.stk[sState.stk_pos++] = BaseAddress;
    }
    if (sValue->mRegister != NULL || sValue->mAddr == NULL || sValue->mSize == 0) {
        str_exception(ERR_INV_DWARF, "invalid DWARF expression reference");
    }
    if (sValue->mForm == FORM_DATA4 || sValue->mForm == FORM_DATA8) {
        if (sValue->mFrame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "need stack frame");
        evaluate_location();
    }
    else {
        evaluate_expression(Unit->mDesc.mSection, sValue->mAddr, sValue->mSize);
    }

    sValue->mAddr = NULL;
    sValue->mValue = 0;
    sValue->mSize = 0;
    sValue->mBigEndian = sState.big_endian;
    sValue->mRegister = NULL;
    sValue->mPieces = NULL;
    sValue->mPieceCnt = 0;

    if (sValuePieces) {
        sValue->mPieces = sValuePieces->mArray;
        sValue->mPieceCnt = sValuePieces->mCnt;
    }
    else if (sState.reg) {
        sValue->mSize = sState.reg->size;
        sValue->mBigEndian = sState.reg->big_endian;
        sValue->mRegister = sState.reg;
    }
    else {
        sValue->mValue = sState.stk[--sState.stk_pos];
    }

    if (sState.stk_pos != stk_pos) {
        str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
    }
}

#endif /* ENABLE_ELF && ENABLE_DebugContext */

Back to the top