Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [tcf-dev] Problem planting breakpoints

>> On the other hand IF I execute iterate_breakpoints() the first breakpoint hit works, but as I hit resume the agent first tries to plant the breakpoints but unfortunately unplants them right after planting which empties my breakpoint list again..

> I'm not sure to understand what component adds the breakpoints? Is that 
a client (Eclipse?) or directly the program hosting the agent?

Well, the only way how I am able to tell where the program is supposed to stop is by receiving these information from Eclipse. So every breakpoint file:lineNr location has to be transmitted first to the agent (which seems to work since iterate_breakpoints() does deliver all breakpoints).

I've now changed a few things which I thought could be the reason for this but still.. this is what happens:

1. PROGRAMMING_SUCCEEDED gets raised
2. call iterate_breakpoints() (at the moment the only way for me to obtain file:lineNr from bps)
3. call RunUntilBreakpointHit()
4. Device runs and hits a breakpoint
5. Eclipse displays correct line and file
6. (User): Hit "resume"
7. TCF Agent calls cpu_bp_plant() (as it should i think)
8. TCF Agent calls cpu_bp_remove() (which removes the bps again)
9. RunUntilBreakpointHit() gets again called (but device will never stop)
10. Eclipse displays "Thread" as running

I have one little guess left..

This is my cpu_bp_plant():

int cpu_bp_plant(ContextBreakpoint * bp) {
    bp->access_types = 0;
    return CLIDevice_PlantBreakpoint(bp->address);
}

Could it be possible that I have to store the whole ContextBreakpoint struct and not just its address and remove the breakpoints according to their struct they belong? I did not try this out, it just came to my mind right now.

I wonder .. do a lot of people have problems like I have? :D

Best regards,
Stefan

Attachment: My version of cpudefs-mdep.c

>
> I really have no idea why this is the case and which event causes this behaviour ..
>
> Best regards.
>
> Stefan
>
>> Please Note that my agent does not communicate with the device directly instead talks to another server that is already capable of doing so.
>>
>>
>>
>> Thank you and best regards,
>> Stefan Falk
>>
>>
>> -----Original Message-----
>> From: tcf-dev-bounces@xxxxxxxxxxx [mailto:tcf-dev-bounces@xxxxxxxxxxx] On Behalf Of Stefan.Falk@xxxxxxxxxxxx
>> Sent: Friday, May 16, 2014 8:47 AM
>> To: tcf-dev@xxxxxxxxxxx
>> Subject: [tcf-dev] Problem planting breakpoints
>>
>> Hi and sorry for my third E-Mail today but I seem to have a major issue with the way how breakpoints are set and removed.
>>
>> Like I said a few times already, all I got is a function CLIDevice_RunUntil(int[] breakpoint_address) to set breakpoints and run my device under debug.
>>
>> Therefore I call iterate_breakpoints() to collect all file locations and map them to their actual memory addresses.
>>
>> My problem is still that after the program reaches a  breakpoint, the TCF Agent begins to "plant" breakpoints. The problem isn't that by doing so cpu_bp_plant() gets called and therefore CLIDevice_PlantBreakpoint() gets called, the problem is that immediately after that cpu_bp_remove() is getting called.
>>
>> I have no idea why this is happening. All I can tell so far is that InstructionRef ref->cnt in validate_bi_refs is zero for some reason the "dirty" flag of BreakInstruction is TRUE gets set there. Therefore it gets deleted later on.
>>
>> I'm really really stuck here. I've tried the whole day to find out what is wrong but I really don't understand the underlying reason why the agent wants to remove my breakpoints ..
>>
>> Thanks for your help.
>>
>> --
>> Stefan Falk
>>
>> Infineon Technologies Austria AG
>> Trainee
>> Automotive Sense and Control
>> Component Verification
>>
>> Tel:  +43 (0)5 / 1777 - 5439
>> Email: stefan.falk@xxxxxxxxxxxx<mailto:stefan.falk@xxxxxxxxxxxx>
>>
>> "Aim above the mark to hit the mark." - Ralph Waldo Emerson
>>
>>
>>
>> _______________________________________________
>> tcf-dev mailing list
>> tcf-dev@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/tcf-dev
>>
>>
>> This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
>>
>> _______________________________________________
>> tcf-dev mailing list
>> tcf-dev@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/tcf-dev
>> _______________________________________________
>> tcf-dev mailing list
>> tcf-dev@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/tcf-dev
>>
> _______________________________________________
> tcf-dev mailing list
> tcf-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/tcf-dev
>
>
>
> _______________________________________________
> tcf-dev mailing list
> tcf-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/tcf-dev
>
_______________________________________________
tcf-dev mailing list
tcf-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/tcf-dev


#include <tcf/config.h>

#if ENABLE_DebugContext && !ENABLE_ContextProxy

#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <tcf/framework/errors.h>
#include <tcf/framework/cpudefs.h>
#include <tcf/framework/context.h>
#include <tcf/framework/myalloc.h>
#include <tcf/framework/trace.h>
#include <tcf/services/symbols.h>
#include <tcf/services/runctrl.h>
#include <machine/mcs51/cpudefs-mdep.h>
#include <DebuggableDevice.cli.h>

#define MAX_REGISTERS 400
#define REG_OFFSET(name) offsetof(REG_SET, name)

RegisterDefinition * regs_index = NULL;
static unsigned int regs_cnt    = 0;

unsigned char BREAK_INST[] = { 0x01 };

static RegisterDefinition regs_def[] = {

#if defined(__i8051__) || defined(__INF_SP3x__) || defined(__INF_SP4x__)

#   define REG_SP SP
#   define REG_IP PC

    // ///////////// Basic function registers

    // Program counter  
    { "PC",     REG_OFFSET(PC),      2, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000,        0 ,0 , "Program Counter" },
    
    // Data pointer register
    { "DPTR",   REG_OFFSET(DPTR),    2, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000,        0 ,0 , "Data Pointer Register" },
    
    // Stack pointer       
    { "SP",     REG_OFFSET(SP),      2, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, REGADDR_SP,    0 ,0 , "Stack Pointer" },
    
    { "A",     REG_OFFSET(A),        1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, REGADDR_ACC,   0 ,0 , "Accumulator A" },
    
    { "B",     REG_OFFSET(B),        1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, REGADDR_B,     0 ,0 , "Accumulator B" },

    // Program status word      
    { "PSW",    REG_OFFSET(PSW),     1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, REGADDR_PSW,   0 ,0 , "Program Status Word" },
    
    // Main purpose registers  
    { "R1",     REG_OFFSET(R1),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R2",     REG_OFFSET(R2),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R3",     REG_OFFSET(R3),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R4",     REG_OFFSET(R4),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R5",     REG_OFFSET(R5),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R6",     REG_OFFSET(R6),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    { "R7",     REG_OFFSET(R7),      1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, NULL,         0, 0x0000 },
    
    // ///////////// Special function registers 
    
    // Data pointer high/low 
    { "DPL",    REG_OFFSET(DPTR),    1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 1, 0, REGADDR_DPL, 0 ,0 , "" },
    { "DPH",    REG_OFFSET(DPTR) + 1,1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, regs_def + 1, 0, REGADDR_DPH, 0 ,0 , "" },
    
#if defined(__INF_SP3x__)
    // Registers for SP3x devices
#elif defined(__INF_SP4x__)
    // Registers for SP4x devices
#endif

#elif 

#   error "No Controller defined"

#endif // __i8051__
    // Terminal entry
    { NULL,     0, 0, 0, 0 }
};

//#define MAX_HW_BPS 26

typedef struct ContextExtensioni8051 {
    int dummy;
} ContextExtensioni8051;

static size_t context_extension_offset = 0;

#define EXT(ctx) ((ContextExtensioni8051 *)((char *)(ctx) + context_extension_offset))

/*
 * Returns RegisterDefinition of the program counter.
 */
RegisterDefinition * get_PC_definition(Context * ctx) {
    static RegisterDefinition * reg_def = NULL;

    if (!context_has_state(ctx)) 
        return NULL;

    if (reg_def == NULL) {
        RegisterDefinition * defs = get_reg_definitions(ctx);

        if (defs != NULL) {

            RegisterDefinition * r;

            for (r = defs; r->name != NULL; r++) {
                if (r->offset == offsetof(REG_SET, REG_IP)) {
                    reg_def = r;
                    break;
                }
            }
        }
    }
    return reg_def;
}

static int set_debug_regs(Context * ctx, int check_ip, int * step_over_hw_bp) {
    int i;
    int ret;
    uint32_t dr7 = 0;
    ContextAddress ip = 0;
    ContextExtensioni8051 * dext = EXT(ctx);
    ContextExtensioni8051 * bps  = EXT(context_get_group(ctx, CONTEXT_GROUP_BREAKPOINT));
    RegisterDefinition *reg_def  = NULL;

    ret = 0;

    if (check_ip) {

        *step_over_hw_bp = 0;

        reg_def = get_PC_definition(ctx);
        ret     = context_read_reg(ctx, reg_def, 0, reg_def->size, &ip);

        if ( ret < 0 )
            return -1;
    }
}

int cpu_bp_plant(ContextBreakpoint * bp) {
    bp->access_types = 0;
    return CLIDevice_PlantBreakpoint(bp->address);
}

int cpu_bp_remove(ContextBreakpoint * bp) {
    return CLIDevice_UnplantBreakpoint(bp->address);
}

int cpu_bp_on_resume(Context * ctx, int * single_step) {

    if(ctx->stopped_by_cb != NULL) {
        if(set_debug_regs(ctx, 1, single_step) < 0) {
            return -1;
        }
    }
    return 0;
}

int cpu_bp_on_suspend(Context * ctx, int * triggered) {
    // TODO
    return -1;
}

int cpu_bp_get_capabilities(Context * ctx) {
    int ret = 0;

    ret = CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE | CTX_BP_ACCESS_INSTRUCTION;

    return ret;
}

/*
 * @return: 0 if OK or negative error value
 */
int crawl_stack_frame(StackFrame * frame, StackFrame * down) {
    // TODO
    return -1;
}

static void add_bit_field(RegisterDefinition * parent,
        unsigned pos, unsigned len, unsigned no_write, const char * name, const char * desc) {
    unsigned i = 0;
    RegisterDefinition * def = regs_index + regs_cnt++;
    assert(regs_cnt < MAX_REGISTERS);
    def->name = name;
    def->dwarf_id = -1;
    def->eh_frame_id = -1;
    def->bits = (int *)loc_alloc_zero(sizeof(int) * (len + 1));
    def->parent = parent;
    def->description = desc;
    def->no_write = no_write;
    while (i < len) def->bits[i++] = pos++;
    def->bits[i++] = -1;
}

#define READONLY 1

void ini_psw_bits()
{
    RegisterDefinition * psw = regs_index;
    while (psw->name != NULL && strcmp(psw->name, "PSW") != 0) psw++;
    if (psw->name == NULL) return;

    add_bit_field(psw,  7, 1, !READONLY, "CY", "Carry");
    add_bit_field(psw,  6, 1, !READONLY, "AC", "Auxiliary Carry");
    add_bit_field(psw,  5, 1, !READONLY, "F0", "Flag 0");
    add_bit_field(psw,  4, 2, !READONLY, "RS", "Register Bank Select");
    add_bit_field(psw,  2, 1, !READONLY, "OV", "Overflow");
    add_bit_field(psw,  1, 1, !READONLY, "F1", "Flag 1");
    add_bit_field(psw,  0, 1,  READONLY, "P",  "Parity");
}

static void ini_i8051_regs(void) {

    RegisterDefinition * def = regs_def;

    while (def->name != NULL) {

        RegisterDefinition * reg = regs_index + regs_cnt++;
        assert(regs_cnt < MAX_REGISTERS);

        *reg = *def; /* keep references to regs_def array (name, role), as it is a static array */
        
        if (def->parent != NULL) {
            reg->parent = regs_index + (def->parent - regs_def);
        }

        def++;
    }

    ini_psw_bits();
}

/*
 * Initializes all RegisterDefinition's for used 
 * Controller.
 */
void ini_cpudefs_mdep(void) {

    regs_cnt = 0;
    regs_index = (RegisterDefinition *)loc_alloc_zero(sizeof(RegisterDefinition) * MAX_REGISTERS);

#if defined (__i8051__)

    ini_i8051_regs();

#if defined(__INF_SP3x__)
    /**** Registers for SP3x devices ****/
#elif defined(__INF_SP4x__)
    /**** Registers for SP4x devices ****/
#endif

#elif 

#   error "No Controller defined"

#endif // __i8051__
}

#endif

Back to the top