#1468 Code size > 64K and linker produces garbage (DS80C400)

closed-out-of-date
linker (61)
sdld
5
2013-06-28
2008-06-20
Jim Bell
No

SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.8.0 #5117 (Mar 23 2008) (MINGW32)

Once the code size crosses 64K, the linker produces garbage.

These two python programs help reproduce it. The first one produces source code: a main program and two large source-code files, and compiles them.

The second one analyzes the resulting .ihx (or .hex) file, looking for gaps or overlaps.

Hope this helps.

#
# GenBig.py
# Written by: Jim Bell (http://jc-bell.com)
#
# This reproduces the SDCC Dallas DS80C400 64K boundary bug.
# It produces three files: Big.c, OtherBig.c and Bug64k1.c
# Big.c and OtherBig.c produce a large number of functions.
# Bug64k1 has the main function that verifies that the highest
# of each Big and OtherBig functions work.
#
# It requires the files from Dallas App Note 3346
# http://www.maxim-ic.com/appnotes.cfm/an_pk/3346
# Put them in the same directory as this script.
#
# This script does the build and link per app note 3346
#
# Fix the SDCC_PATH variable below for your environment.
#
import sys;
import os;

# 247 works, 248 doesn't. w/rominit commented out: 250 works
NUM_FUNCS=252
MAGIC_NUM=249 # 250 if you comment out init_romexport in startup400.a51

SDCC_PATH="C:\\Software\\Open\\app\\SDCC\\bin"
CFLAGS="-mds400 --model-flat24 --stack-10bit"
LFLAGS="-Wl-r --xram-loc 0x10000 --xram-size 0x3fff --code-loc 0x400000"
SDCC = os.path.join(SDCC_PATH, "sdcc");
PACKIHX = os.path.join(SDCC_PATH, "packihx");
ASX = os.path.join(SDCC_PATH, "asx8051");

bigPfx = [ "Big", "OtherBig" ]
mainPfx = "Bug64k1"

def WriteFunc(f, x, pfx):
f.write("""
unsigned long int %(var)s;

void %(func)s(void)
{
if (%(var)s > 1)
{ %(var)s += %(val)d; }
else
{ %(var)s -= 1; }
}
""" %
{
'func' : "F%s%d" % (pfx,x),
'var' : "v%s%d" % (pfx,x),
'val' : x
});

def WriteBigFile(pfxName, nFuncs):
f = file(pfxName + ".c", "w");

print ("%s.c: %s%d" % (pfxName,pfxName,nFuncs))
for x in range(nFuncs):
WriteFunc(f, x+1, pfxName);

f.close();

def WriteMain(baseFn, n):
f = file(baseFn + ".c", "w");
f.write("""
#include <stdio.h>
extern unsigned long vBig%(total)d;
extern void FBig%(total)d(void);
extern unsigned long vOtherBig%(total)d;
extern void FOtherBig%(total)d(void);

void main(void)
{
unsigned long int myVal, myOtherVal;
unsigned long int myRef, myOtherRef;
printf(\"Welcome. Functions:%(total)d.\\n\");
vBig%(total)d= 88;
myRef = 88 + %(total)d;
vOtherBig%(total)d = 9988;
myOtherRef = 9988 + %(total)d;
FBig%(total)d();
myVal = vBig%(total)d;
FOtherBig%(total)d();
myOtherVal = vOtherBig%(total)d;
printf(\"The functions returned. Did they work? %%lu==%%lu? %%lu==%%lu?.\\n\",
myVal, myRef, myOtherVal, myOtherRef);
while (1) { }
}
""" % { 'total' : n});
f.close();

def RunCmd(c):
r = os.system(c)
if (r != 0):
print "\t%s\nFailed: error code %d" % (c,r)
raise SystemExit

def DoCompile(baseFn):
print "Compiling " + baseFn + ".c"
RunCmd("%s %s --no-xinit-opt --codeseg %s -c %s.c" % (SDCC, CFLAGS, baseFn, baseFn));

def DoLink(mainPfx, pfxList):
print "Assembling startup400.a51"
RunCmd(ASX + " -losffgp startup400.a51");
print "Linking";
relList = mainPfx + ".rel startup400.rel";
for b in pfxList:
relList = relList + " " + b + ".rel";

RunCmd("%s %s %s %s -l rominit.lib" % (SDCC, CFLAGS, LFLAGS, relList));
RunCmd("%s %s.ihx > %s.hex" % (PACKIHX, mainPfx, mainPfx));

#
# Main code.
#
n = NUM_FUNCS; #int(sys.argv[1])
# print "Here we are, and sys.argv[1] is ", n
for b in bigPfx:
WriteBigFile(b, n);
WriteMain(mainPfx, n);

for b in bigPfx:
DoCompile(b);

DoCompile(mainPfx);
DoLink(mainPfx, bigPfx);
willWork = ""
if (n > MAGIC_NUM):
willWork = " NOT"
print "\nDone. This should%s work. Load %s.hex" % (willWork, mainPfx)
################### End of GenBig.py ####################

#
# ProcIhx.py -- Analyze the .ihx and .hex linker output files.
#
import sys;
import os;

def Assert(cond):
if (not cond):
raise Exception, "Assertion failed"

# global reptCount;
reptCount = 0;

class Ctxt:
def __init__(self, fn="", ln=0):
self.fileName = fn;
self.lineNum = ln;
pass

def str(self):
return "%s, line %d" % (self.fileName, self.lineNum)

def Report(self, x):
print self.str() + ":", x
global reptCount;
reptCount = reptCount + 1;
#if (reptCount > 10):
# raise SystemExit

class MemBlk:
def __init__(self, addr, hd, ct):
self.addr32 = addr;
self.hexData = hd;
self.fileName = ct.fileName;
self.lineNum = ct.lineNum;
pass;

def NumBytes(self):
return len(self.hexData) / 2;

def Empty(self):
return len(self.hexData) == 0;

def HiBound(self):
return self.addr32 + self.NumBytes();

def LoBound(self):
return self.addr32;

def str(self):
return "%2d b @ %X" % (len(self.hexData)/2, self.addr32);

def Report(self, x):
print self.str() + ": " + x;

def ReadFile(fn, myMem):
addrHi16 = 0;
myMem.clear();
lnCnt = 0;
atEof = False;
fCtxt = Ctxt(fn);
for ln in file(fn, "r"):
lnCnt += 1;
fCtxt.lineNum = lnCnt;
if len(ln) <= 0:
fCtxt.Report("Blank line");
continue
Assert(ln[0] == ':');
# :0E003600E0D0E0D0E0D0E0900103E07458F09C
nData = int(ln[1:3], 16) * 2; # *2 -> hex bytes
# print ln[1:3], " ", ln[3:7], " ", ln[7:9], " ", ln[9:9+nData], " ", ln[9+nData:9+nData+2], ">>>", ln[11+nData:]
addr16 = int(ln[3:7], 16);
recType = ln[7:9]
data = ln[9:9+nData]
if (len(ln) - nData != 12):
fCtxt.Report("Extraneous data: " + ln[11+nData:]);
if (recType == '00'): # data
# store it
if (atEof):
fCtxt.Report("Data found after EOF");
addr32 = addrHi16 | addr16;
if (addr32 in myMem):
fCtxt.Report("Memory already defined, line " + myMem[addr32].str());
else:
myMem[addr32] = MemBlk(addr32, data, fCtxt);
elif (recType == '01'): # EOF
atEof = True;
elif (recType == '02'): # Extended Segment Address
fCtxt.Report("We don't consider extended segment address records");
elif (recType == '04'):
if (len(data) != 4):
fCtxt.Report("Expecting 4 hex-digits of extended linear address, but found '%s'" % data);
addrHi16 = int(data, 16) << 16;
fCtxt.Report("Extended linear address %X" % addrHi16);
else:
fCtxt.Report("Unknown record type '%s'" % recType);
# presume the checksum is ok
# post-loop

def CheckMem(myMem):
prevMB = MemBlk(0x400000, "", Ctxt(""));
nOvlaps = nGaps = nRecs = 0;
for addr,mb in sorted(myMem.iteritems()):
nRecs += 1;
if (addr == prevMB.addr32) and not prevMB.Empty():
mb.Report("Memory start-overlap w/block " + prevMB.str());
elif (mb.LoBound() < prevMB.HiBound()):
mb.Report("Memory overlap (%d bytes) %s" % (prevMB.HiBound() - mb.LoBound(), prevMB.str()));
nOvlaps += 1;
elif (mb.LoBound() > prevMB.HiBound()):
prevMB.Report(" -- Memory gap (%6d bytes) -- %s" % (mb.LoBound() - prevMB.HiBound(), mb.str()));
nGaps += 1;
prevMB = mb;

print "%d recs: %d gaps; %d overlaps" % (nRecs, nGaps, nOvlaps)

mem1 = dict()
ReadFile("Bug64k1.ihx", mem1);
CheckMem(mem1);
##################### End of ProcIhx.py ####

Discussion

  • Jim Bell

    Jim Bell - 2008-06-20

    Logged In: YES
    user_id=1804579
    Originator: YES

    File Added: GenBig.py

     
  • Jim Bell

    Jim Bell - 2008-06-20

    Generates big source-code files and builds them.

     
  • Jim Bell

    Jim Bell - 2008-06-20

    Logged In: YES
    user_id=1804579
    Originator: YES

    File Added: ProcIhx.py

     
  • Jim Bell

    Jim Bell - 2008-06-20

    Looks over the .ihx and .hex output for gaps and overlaps.

     
  • Jim Bell

    Jim Bell - 2008-06-20
    • labels: 103823 --> linker
     
  • Jim Bell

    Jim Bell - 2008-06-20

    Logged In: YES
    user_id=1804579
    Originator: YES

    Please forgive the long code paste. I didn't realize you could add individual files in the follow-up. (I added them there.) Nor did I realize it would zap the indentation, rendering it useless. (FWIW, if you "view source" on the HTML, the indentation's still there.)

     
  • Maarten Brock

    Maarten Brock - 2011-12-28
    • milestone: --> unreproducable
    • assigned_to: nobody --> maartenbrock
    • status: open --> pending-out-of-date
     
  • Maarten Brock

    Maarten Brock - 2011-12-28

    Although app note 3346 can still be found on the Dallas website all links to the accompanying libraries are dead. So I think I will not be able to reproduce this bug as it states it requires those files.

    Also it is very unclear what the bug actually is. What am I to expect from these scripts and why is that wrong?

    I therefore set this bug pending and it will automatically close if nobody responds in the next few weeks. If anyone is interested in getting this fixed I would really prefer to get those generated source files instead of their generator attached. And of course the necessary libraries.

     
  • Maarten Brock

    Maarten Brock - 2013-06-28

    I don't know how this pending item never got closed, so I close it now.

     
  • Maarten Brock

    Maarten Brock - 2013-06-28
    • status: pending-out-of-date --> closed-out-of-date
    • Category: --> sdld
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks