Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#1442 ROM pointer to struct member not initialized

closed-fixed
Maarten Brock
5
2013-05-25
2008-03-28
Patryk
No

Ptr2 in code below doesn't get initialized, even space for it isn't reserved, no matter what space it points to. When pointer is placed in other space than CODE, then all is OK, also when it points to member of type other than struct.
This bug is dangerous in ROM tables of (size, pointer) pairs. Silently missed initialization of pointer only (size gets initialized) messes up whole table above unlucky entry.
Code is simplified here - I have defined many such pointers:
#define MY_DATA_STR_PTR \ ((__code const TMy_data_str *)(0x3800))
and am using them to define pointers in tables.
This bug was present in SDCC since I first use it: 2.5.0.

-------
Source:
typedef struct
{
char a;
struct { char c; } s;
} TStr;

__code const TStr Str = { 0, {0} };

char * __code const Ptr1 = // OK
&(Str.a);

char * __code const Ptr2 = // not initialized
&(((__code const TStr *)(0x1234))->s.c);

char * __code const Ptr3 = // OK
&(Str.s.c);

--------------
Generated asm:
.area CONST (CODE)
G$Str$0$0 == .
_Str:
.db #0x00
.db #0x00
G$Ptr1$0$0 == .
_Ptr1:
.byte (_Str + 0),((_Str + 0) >> 8),#0x80
G$Ptr2$0$0 == .
_Ptr2:
G$Ptr3$0$0 == .
_Ptr3:
.byte ((_Str + 1) + 0),(((_Str + 1) + 0) >> 8),#0x80
.area XINIT (CODE)

SDCC version:
mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.8.0
#5117 (Mar 23 2008) (MINGW32)
command line:
sdcc.exe -c --debug --use-stdout -V --std-sdcc99 -I... Source8.c

WXP HE PL SP2, AMD Athlon XP 1700+

Discussion

  • Robert Larice
    Robert Larice
    2008-04-04

    Logged In: YES
    user_id=1840151
    Originator: NO

    for debugging purpose I suggest to reduce to the following piece of code,
    and to use target mcs51

    -----<8-------
    struct st { char a[1]; };

    char xdata * const Ptr = &(((struct st xdata *) 0x1234) -> a[0]);
    ----->8-------

    the following gdb commands:

    -----<8------
    set args -c 1928022-11z-minimal.c

    break valForArray
    command
    backtrace
    call PA(arrExpr)
    set $the_cast = arrExpr->left->left
    end

    run
    ----->8------

    will then print:

    Breakpoint 1, valForArray (arrExpr=0x82d3720) at SDCCval.c:1922
    #0 valForArray (arrExpr=0x82d3720) at SDCCval.c:1922
    #1 0x080c68ee in initPointer (ilist=0x82d37d0, toType=0x82d28b0) at SDCCglue.c:441
    #2 0x080c8e43 in printIvalPtr (sym=0x82d2970, type=0x82d28b0, ilist=0x82d37d0, oBuf=0x82485cc) at SDCCglue.c:1079
    #3 0x080c9f2d in printIval (sym=0x82d2970, type=0x82d28b0, ilist=0x82d37d0, oBuf=0x82485cc) at SDCCglue.c:1209
    #4 0x080ca395 in emitStaticSeg (map=0x824a620, oBuf=0x82485cc) at SDCCglue.c:1288
    #5 0x080ca8db in emitMaps () at SDCCglue.c:1350
    #6 0x080cb416 in glue () at SDCCglue.c:1596
    #7 0x0805799f in main (argc=3, argv=0xbfe2b634, envp=0xbfe2b644) at SDCCmain.c:2420

    :ARRAY_OP (0x82d3720) type (xdata-char)
    : PTR_ACCESS (0x82d3530) type (char xdata-[1] )
    : CAST (0x82d3040) from type (literal-int) to type (struct st xdata* )
    : CONSTANT (0x82d2f90) value = 4660, 0x1234, 4660.000000 type (literal-int)
    : SYMBOL (a=0x82d34d8 @ 0x82d3248)
    : CONSTANT (0x82d36c8) value = 0, 0x0, 0.000000 type (literal-unsigned-char)

    ----------------------------

    I think the function
    valForArray (ast * arrExpr)
    in SDCCval.c, is not prepared to hande this CAST sub-ast.

    the following patch, seems to successfully work around this problem.
    but it is very rough, and only usefull to express the idea.

    ===================================================================
    --- SDCCval.c (Revision 5131)
    +++ SDCCval.c (Arbeitskopie)
    @@ -1935,6 +1935,12 @@
    IS_ADDRESS_OF_OP (arrExpr->left->left))
    lval = valForStructElem (arrExpr->left->left->left,
    arrExpr->left->right);
    + /*larice blatant hack */
    + else if (IS_AST_OP (arrExpr->left->left) &&
    + arrExpr->left->left->opval.op == CAST &&
    + IS_LITERAL (arrExpr->left->left->right->ftype))
    + lval = valCastLiteral (arrExpr->left->left->ftype,
    + floatFromVal (arrExpr->left->left->right->opval.val));
    else
    return NULL;

    @@ -1953,6 +1959,9 @@
    else
    {
    SNPRINTF (buffer, sizeof(buffer), "%s", lval->name);
    + /*larice blatant hack*/
    + if( SPEC_SCLS (lval->etype) == S_LITERAL )
    + SNPRINTF (buffer, sizeof(buffer), "0x%04x", SPEC_CVAL (lval->etype).v_ulong);
    }

    SNPRINTF (val->name, sizeof(val->name), "(%s + %d)", buffer,

    ==========================================================

    finally I'd like to propose a support/regression/test file,
    which successfully discriminates the orignal from the patched sdcc.

    --------------------<8--------------------------------------
    /*
    */

    // bug1928022
    //
    // Due to incompletness of the function
    // value *valForArray (ast * arrExpr)
    // in SDCCval.c
    // the following "C"
    //
    // struct st { char a[1]; };
    // char xdata * const Ptr = &(((struct st xdata *) 0x1234) -> a[0]);
    //
    // will generate an .asm where a label for `Ptr' is generated,
    // but no space is allocated, and no initialization is done.
    //
    // In this piece of regression test,
    // the `Fill...' variables are used to work around
    // the missing space allocation.
    // The cmp() will then reliably bump into those Fill.. locations
    //
    // due to authors lazyness, this test is limited to mcs51
    // though other targets suffer from the same problem

    #include <testfwk.h>

    #if defined(SDCC_mcs51)

    struct st_a { char a[2]; };

    char xdata * const Ptr_a1 = &(((struct st_a xdata *) 0x1234) -> a[0]);
    char xdata * const Ptr_a2 = &(((struct st_a xdata *) 0x1234) -> a[1]);
    long const Fill_a = -1;

    struct st_b { long a[2]; };

    long xdata * const Ptr_b1 = &(((struct st_b xdata *) 0x1234) -> a[0]);
    long xdata * const Ptr_b2 = &(((struct st_b xdata *) 0x1234) -> a[1]);
    long const Fill_b = -1;

    char cmp(void *a, void *b) { return a == b; }

    void
    testBug(void)
    {
    ASSERT( cmp(Ptr_a1, (char xdata *) 0x1234) );
    ASSERT( cmp(Ptr_a2, (char xdata *) 0x1235) );
    ASSERT( cmp(Ptr_b1, (char xdata *) 0x1234) );
    ASSERT( cmp(Ptr_b2, (char xdata *) 0x1238) );
    }

    #else

    void
    testBug(void)
    {
    ASSERT(1);
    }

    #endif

    /*
    * Local Variables:
    * compile-command: "make -C .. -k test-port PORT=mcs51-small"
    * compile-command: "make -C .. -k port-results PORT=mcs51-small PORT_RESULTS=results/mcs51-small/1928022-11z-test.out"
    * End:
    */

    -------------------->8--------------------------------------

    Robert Larice

     
  • Patryk
    Patryk
    2009-09-21

    It may me the same as #2806238:
    pointer to function becomes NULL in struct

     
  • Maarten Brock
    Maarten Brock
    2009-11-01

    Fixed in SDCC 2.9.4 #5560.
    Was not related to 2806238. It was about constant folding in decorateType and being able to handle non-symbol values in several places.

     
  • Maarten Brock
    Maarten Brock
    2009-11-01

    • labels: --> C-Front End
    • milestone: --> fixed
    • assigned_to: nobody --> maartenbrock
    • status: open --> closed-fixed