From: SourceForge.net <no...@so...> - 2011-02-21 16:53:50
|
Bugs item #3188357, was opened at 2011-02-21 16:53 Message generated for change (Tracker Item Submitted) made by u6c87 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100599&aid=3188357&group_id=599 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: z80 port Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Brian Ruthven (u6c87) Assigned to: Nobody/Anonymous (nobody) Summary: Stack imbalance across memcpy call Initial Comment: I've found some strange crashes resulting from the call to memcpy(). I've reproduced this using --no-peep (to eliminate this as a possible cause). I've found that including <string.h> and using memcpy() can result in a stack push/pop imbalance which causes problems along the way, most obviously with the "pop ix / ret" pair at the end. I believe I've reduced this to the following test case, but I accept I might have missed something. Testcase: ========== #include <string.h> char buf[20]; void terminate_filename(char *filename) { int len = strlen(filename); memcpy(buf, filename, len); buf[len] = 0xff; } ========== Compile this using: $ sdcc -mz80 --no-peep -c memcpy_testcase.c and around the call to memcpy, you get: ========== ;memcpy_testcase.c:14: memcpy(buf, filename, len); ld e,4 (ix) ld d,5 (ix) push bc ld hl,#_buf push hl <== note arg order pushed is dst, src, len push de push bc call _memcpy pop bc <=============== only bc popped ;memcpy_testcase.c:15: buf[len] = 0xff; ========== Note that only the first "push bc" is undone after the "call _memcpy", and the 3 words from hl,de,bc for memcpy() args are not explicitly popped afterwards. sdcc -E gives this for the code fed to the compiler: __builtin_memcpy(buf, filename, len); If I add "#undef memcpy" after the "#include <string.h>", then the code generated includes 3 * "pop af" to consume the arguments from the stack: ========== ;memcpy_testcase.c:14: memcpy(buf, filename, len); ld e,4 (ix) ld d,5 (ix) push bc push bc <== note arg order pushed is len, src, dst push de ld hl,#_buf push hl call _memcpy pop af <============== stacked args popped (x3) pop af pop af pop bc <============== restore saved bc ;memcpy_testcase.c:15: buf[len] = 0xff; ========== It seems there are two issues at work here: 1) The stack imbalance means that the resulting "pop ix / ret" pair grabs a random value for ix, then jumps to a random location. 2) The arguments for _memcpy seem to be stacked in the reverse order when using __builtin_memcpy, even when this simply resolves to _memcpy. This results in one of the pointers being used as the count, and most of memory is trashed in the process. Given my program location (around 0x8300), src/dst string location (~0x9000), and string length (0xc), issue #2 results in most of RAM being trashed, and assuming the damage extends up to the location of memcpy(), then random instructions are executed as memcpy itself is overwritten. In the simple case above, the wrong value is restored into bc, garbage is popped into ix, then ret executed to a random location. In larger functions which have some local variables, issue #1 is mitigated somewhat by the explicit "ld sp, ix" instruction. However, any later calculations based on %sp later in the function are thrown off by the additional 3 words still on the stack, not to mention bc is restored to the wrong value. This only seems to happen if the number of bytes to copy is not a constant known at compile time. 1) I've attached a tarball with the .c code, the .lst output files both with and without the workaround. 2) Compile line: $ sdcc -mz80 --no-peep -c memcpy_testcase.c 3) SDCC version: $ sdcc -v SDCC : z80 3.0.1 #6241 (Feb 21 2011) (Solaris i386) 4) Expected behaviour: copy of 'n' bytes from src to dst. Observed behaviour: Memory trashed, then "random" jump causes crash. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=100599&aid=3188357&group_id=599 |