Package: libsdl1.2-dev Version: 1.2.13-1 Severity: important Justification: Violation of SYS V ABI specification
Hello, Christoph Mallon, the driving coder behind ja2 stracciatella [0], has discovered a serious problem. libsdl is violating the SYS V ABI (x86) [1]. There it is stated that the "direction flag must be set to the "forward" (that is, zero) direction before entry and upon exit." [2]. But as the program in the attachment demonstrates ([3]) libsdl doesn't do that always. If you use SDL_BlitSurface(), the direction flag is set after exiting the function. This problem occurs because SDL_BlitSurface() calls SDL_revcpy(), the sequence is: SDL_BlitSurface() (#define SDL_Blit_Surface SDL_BlitUpper) SDL_BlitUpper() SDL_BlitLower() src->map->sw_blit() (function pointer to SDL_SoftBlit()) SDL_SoftBlit() src->map->sw_data->blit() (function pointer to SDL_BlitCopyOverlap()) SDL_BlitCopyOverlap() SDL_revcpy() SDL_revcpy() sets but doesn't clear the direction flag. The incriminating code is to be found in SDL_stdinc.h: > #if defined(__GNUC__) && defined(i386) > #define SDL_revcpy(dst, src, len) \ > do { \ > int u0, u1, u2; \ > char *dstp = (char *)(dst); \ > char *srcp = (char *)(src); \ > int n = (len); \ > if ( n >= 4 ) { \ > __asm__ __volatile__ ( \ > "std\n\t" \ > "rep ; movsl\n\t" \ > : "=&c" (u0), "=&D" (u1), "=&S" (u2) \ > : "0" (n >> 2), \ > "1" (dstp+(n-4)), "2" (srcp+(n-4)) \ > : "memory" ); \ > } \ > switch (n & 3) { \ > case 3: dstp[2] = srcp[2]; \ > case 2: dstp[1] = srcp[1]; \ > case 1: dstp[0] = srcp[0]; \ > break; \ > default: \ > break; \ > } \ > } while(0) > #endif As a sidenote: in the GCC 4.3 changelog it is stated that: "It is now invalid to set the flag in asm statement without reseting it afterward.". Kind regards, Kai P.S.: Please CC Christoph always! [0] http://ja2.dragonriders.de/ [1] http://www.sco.com/developers/devspecs/abi386-4.pdf [2] [1], page 38, EFLAGS [3] Used build command: cc -O `sdl-config --cflags --libs` sdl_bug.c -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (500, 'testing') Architecture: i386 (i686) Kernel: Linux 2.6.22.10-cabal Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to de_DE.UTF-8) Shell: /bin/sh linked to /bin/bash -- Kai Wasserbäch (Kai Wasserbaech) E-Mail: [EMAIL PROTECTED] Jabber (debianforum.de): Drizzt URL: http://wiki.debianforum.de/Drizzt_Do%27Urden GnuPG: 0xE1DE59D2 0600 96CE F3C8 E733 E5B6 1587 A309 D76C E1DE 59D2 (http://pgpkeys.pca.dfn.de/pks/lookup?search=0xE1DE59D2&fingerprint=on&hash=on&op=vindex)
#include <SDL.h> #include <stdio.h> #include <stdlib.h> static inline int TestDirectionFlag(void) { unsigned eflags; __asm__ __volatile__("pushf\n\tpop %0" : "=r" (eflags)); return (eflags & 0x400) != 0; } int main(void) { SDL_Init(SDL_INIT_VIDEO); SDL_Surface* const s = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE); SDL_Rect src_rect = { 0, 0, 630, 470 }; SDL_Rect dst_rect = { 10, 10, 630, 470 }; if (TestDirectionFlag()) { fputs("direction flag set BEFORE SDL_BlitSurface()\n", stderr); abort(); } SDL_BlitSurface(s, &src_rect, s, &dst_rect); if (TestDirectionFlag()) { fputs("direction flag set AFTER SDL_BlitSurface()\n", stderr); abort(); } SDL_Quit(); return 0; }
signature.asc
Description: OpenPGP digital signature