* Problem with library images on Windows (again)
@ 2005-05-18 15:53 Juanma Barranquero
2005-05-18 19:30 ` Andreas Schwab
2005-05-18 22:16 ` Jason Rumney
0 siblings, 2 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-18 15:53 UTC (permalink / raw)
For some time now, TIFF images do crash optimized MSVC builds of Emacs
when using the MinGW-supplied TIFF library.
The crash happens in image_spec_value(), but it all boils down to the
fact that on lookup_image(), after
img->load_failed_p = img->type->load (f, img) == 0;
the value of the argument "spec" cannot be trusted. This is easy to prove; with
static LispObject spec_backup;
spec_backup = spec;
img->load_failed_p = img->type->load (f, img) == 0;
spec = spec_backup;
spec_backup = Qnil;
everything works as expected.
Now, when this happened before (with the local variable img) someone
said that the MinGW libraries were not respecting calling conventions,
but I'm not sure. Calling conventions for MSVC say that you cannot
trust EAX, EBX, ECX, EDX, ESI, or EDI registers after a subroutine
call, and AFAICS, the problem is that on optimized builds VC is
expecting spec to still be cached in a register.
So, I can apply the attached patch and at least stop Emacs from
crashing on Windows, but I certainly would appreciate a more
insightful analysis from the "people in the know" wrt image support
and/or Windows.
--
/L/e/k/t/u
Index: src/image.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/image.c,v
retrieving revision 1.23
diff -u -2 -r1.23 image.c
--- src/image.c 10 May 2005 09:16:46 -0000 1.23
+++ src/image.c 18 May 2005 15:38:22 -0000
@@ -1663,9 +1663,20 @@
extern Lisp_Object Qpostscript;
+#ifdef _MSC_VER
+ static Lisp_Object spec_backup;
+ spec_backup = spec;
+#endif
+
BLOCK_INPUT;
img = make_image (spec, hash);
cache_image (f, img);
+
img->load_failed_p = img->type->load (f, img) == 0;
+#ifdef _MSC_VER
+ spec = spec_backup;
+ spec_backup = Qnil;
+#endif
+
/* If we can't load the image, and we don't have a width and
height, use some arbitrary width and height so that we can
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 15:53 Problem with library images on Windows (again) Juanma Barranquero
@ 2005-05-18 19:30 ` Andreas Schwab
2005-05-18 22:44 ` Juanma Barranquero
2005-05-18 22:16 ` Jason Rumney
1 sibling, 1 reply; 37+ messages in thread
From: Andreas Schwab @ 2005-05-18 19:30 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
> Now, when this happened before (with the local variable img) someone
> said that the MinGW libraries were not respecting calling conventions,
> but I'm not sure. Calling conventions for MSVC say that you cannot
> trust EAX, EBX, ECX, EDX, ESI, or EDI registers after a subroutine
That's quite different from the Unix calling conventions on i386, where
only EAX, ECX and EDX are call-clobbered.
> call, and AFAICS, the problem is that on optimized builds VC is
> expecting spec to still be cached in a register.
That appears like a blatant bug in the compiler if it cannot properly
track call-clobbered registers.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 15:53 Problem with library images on Windows (again) Juanma Barranquero
2005-05-18 19:30 ` Andreas Schwab
@ 2005-05-18 22:16 ` Jason Rumney
2005-05-18 22:52 ` Juanma Barranquero
1 sibling, 1 reply; 37+ messages in thread
From: Jason Rumney @ 2005-05-18 22:16 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
>
> So, I can apply the attached patch and at least stop Emacs from
> crashing on Windows, but I certainly would appreciate a more
> insightful analysis from the "people in the know" wrt image support
> and/or Windows.
Better to disable image support for MSVC builds than to try to hack
things to work by introducing redundant variables to save the values
of other variables in. Such hacks might be worth it to support free
software where we can see whether the hack really does fix the
problem, but not for proprietary blackboxes.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 19:30 ` Andreas Schwab
@ 2005-05-18 22:44 ` Juanma Barranquero
2005-05-19 6:58 ` Jason Rumney
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-18 22:44 UTC (permalink / raw)
> That's quite different from the Unix calling conventions on i386, where
> only EAX, ECX and EDX are call-clobbered.
I was wrong wrt the MSVC calling conventions. MSDN docs say:
All arguments are widened to 32 bits when they are passed.
Return values are also widened to 32 bits and returned in the
EAX register, except for 8-byte structures, which are returned
in the EDX:EAX register pair. Larger structures are returned
in the EAX register as pointers to hidden return structures.
Parameters are pushed onto the stack from right to left.
The compiler generates prolog and epilog code to save and
restore the ESI, EDI, EBX, and EBP registers, if they are used
in the function.
so it seems it's the same calling convention than on i386 Unixes: EAX
and EDX can be clobbered to return the function's result, and ECX
because it is not saved.
> That appears like a blatant bug in the compiler if it cannot properly
> track call-clobbered registers.
There's a bug somewhere, that's pretty clear. Whether that's an error
of the MSVC compiler or the MinGW libraries, I'm not sure yet. I've
been tracing lookup_image, and the fact is, the lookup_image code is
using EBX to cache "spec", and rightly so. But the call to tiff_load
(via img->type->load()) clobbers EBX!
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 22:16 ` Jason Rumney
@ 2005-05-18 22:52 ` Juanma Barranquero
2005-05-19 3:50 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-18 22:52 UTC (permalink / raw)
> Better to disable image support for MSVC builds than to try to hack
> things to work by introducing redundant variables to save the values
> of other variables in.
Perhaps; note that I didn't say it wasn't a hack. OTOH, I normally use
a MSVC build and certainly don't appreciate Emacs crashing on me just
because I accidentally opened a TIFF file. But disabling all image
support seems a bit extreme.
Anyway: tiff_load is pushing EBX into the stack and getting a
different EBX when poping it out at the end of the function! I've not
yet traced it to determine what or when it's changing the stack, or
whether it is the MSVC-generated tiff_load code or the MinGW-built
TIFF libraries that are called on several spots of tiff_load, but in
any case something's afoot (as Sherlock Holmes would say).
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 22:52 ` Juanma Barranquero
@ 2005-05-19 3:50 ` Eli Zaretskii
2005-05-19 8:13 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-19 3:50 UTC (permalink / raw)
Cc: emacs-devel
> Date: Thu, 19 May 2005 00:52:56 +0200
> From: Juanma Barranquero <lekktu@gmail.com>
>
> Anyway: tiff_load is pushing EBX into the stack and getting a
> different EBX when poping it out at the end of the function!
Can you set a watchpoint on the address where EBX is saved on the
stack, and then see what code clobbers that value?
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-18 22:44 ` Juanma Barranquero
@ 2005-05-19 6:58 ` Jason Rumney
0 siblings, 0 replies; 37+ messages in thread
From: Jason Rumney @ 2005-05-19 6:58 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
>> That appears like a blatant bug in the compiler if it cannot properly
>> track call-clobbered registers.
>
> There's a bug somewhere, that's pretty clear. Whether that's an error
> of the MSVC compiler or the MinGW libraries, I'm not sure yet.
FWIW the problem with the jpeg library was that the headers defined
some constant like BOOL or BYTE differently than the MSVC headers,
so it ended up a different size.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-19 3:50 ` Eli Zaretskii
@ 2005-05-19 8:13 ` Juanma Barranquero
2005-05-19 19:05 ` Eli Zaretskii
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-19 8:13 UTC (permalink / raw)
On 5/19/05, Eli Zaretskii <eliz@gnu.org> wrote:
> Can you set a watchpoint on the address where EBX is saved on the
> stack, and then see what code clobbers that value?
Yes. tiff_load pushes EBX into the stack, and then goes around happily
pushing arguments and calling functions from the TIFF library, which
apparently don't remove their arguments from the stack (nor does it
the tiff_load code). So the stack keeps growing and, by the time
tiff_load does the POP EBX, it gets random garbage. On returning from
tiff_load the frame pointer is restored, so the spurious stack data is
just discarded.
So it seems like a mismatch between the calling convention used to
implement the TIFF library and the one MSVC thinks the TIFF functions
are using.
I'll dig around a little more. But any help is much appreciated.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-19 8:13 ` Juanma Barranquero
@ 2005-05-19 19:05 ` Eli Zaretskii
2005-05-19 19:31 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-19 19:05 UTC (permalink / raw)
Cc: emacs-devel
> Date: Thu, 19 May 2005 10:13:23 +0200
> From: Juanma Barranquero <lekktu@gmail.com>
>
> tiff_load pushes EBX into the stack, and then goes around happily
> pushing arguments and calling functions from the TIFF library, which
> apparently don't remove their arguments from the stack (nor does it
> the tiff_load code). So the stack keeps growing
This sounds incredible. MSVC generally produces good code, so I find
it hard to believe that it violates the C ABI, whereby the caller
should pop arguments off the stack. Are you sure this is indeed what
happens? Can you show some evidence, like disassembly of code around
the call to tiff_load, which would show how arguments are pushed onto
the stack and never popped off it?
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-19 19:05 ` Eli Zaretskii
@ 2005-05-19 19:31 ` Juanma Barranquero
2005-05-19 19:32 ` Juanma Barranquero
2005-05-20 7:20 ` Eli Zaretskii
0 siblings, 2 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-19 19:31 UTC (permalink / raw)
> This sounds incredible. MSVC generally produces good code, so I find
> it hard to believe that it violates the C ABI, whereby the caller
> should pop arguments off the stack. Are you sure this is indeed what
> happens?
Yes. If, immediately before the POP EBX, I manually restore the stack
to the value it had after the PUSH EBX at the start of the routine,
Emacs does not crash, and indeed it displays the TIFF file.
But I don't think is an error in MSVC. I think it's some mixup between
"pascal" and "C" style calls (as you know, the former remove their
arguments, the latter don't). MSVC must be thinking that the external
TIFF functions do remove their arguments, so it is not doing it.
Sounds like an issue with the external declarations on the header
files.
> Can you show some evidence, like disassembly of code around
> the call to tiff_load, which would show how arguments are pushed onto
> the stack and never popped off it?
There goes the full tiff_load code, as shown on the Visual Studio
disassembler view. You can see by yourself that, when calling Emacs
functions, MSVC uses "ADD SP, nn" to fix the stack, but it doesn't do
it after the indirect calls to fn_TIFF* functions.
--
/L/e/k/t/u
----------------------------------------------------------------------------------------
/* Load TIFF image IMG for use on frame F. Value is non-zero if
successful. */
static int
tiff_load (f, img)
struct frame *f;
struct image *img;
{
01074117 push ebp
01074118 mov ebp,esp
0107411A sub esp,24h
0107411D push ebx
Lisp_Object file, specified_file;
Lisp_Object specified_data;
TIFF *tiff;
int width, height, x, y;
uint32 *buf;
int rc;
XImagePtr ximg;
struct gcpro gcpro1;
tiff_memory_source memsrc;
specified_file = image_spec_value (img->spec, QCfile, NULL);
0107411E mov ebx,dword ptr [ebp+0Ch]
01074121 mov ecx,dword ptr [ebx+28h]
01074124 push esi
01074125 push edi
01074126 xor edi,edi
01074128 push edi
01074129 push dword ptr [_QCfile (1109E80h)]
0107412F call image_spec_value (106FF15h)
specified_data = image_spec_value (img->spec, QCdata, NULL);
01074134 mov ecx,dword ptr [ebx+28h]
01074137 push edi
01074138 push dword ptr [_QCdata (1109064h)]
0107413E mov dword ptr [specified_file],eax
01074141 call image_spec_value (106FF15h)
01074146 add esp,10h
file = Qnil;
GCPRO1 (file);
fn_TIFFSetErrorHandler (tiff_error_handler);
01074149 push offset tiff_error_handler (10723B8h)
0107414E mov esi,eax
01074150 call dword ptr [_fn_TIFFSetErrorHandler (1138B64h)]
fn_TIFFSetWarningHandler (tiff_warning_handler);
01074156 push offset tiff_warning_handler (1072400h)
0107415B call dword ptr [_fn_TIFFSetWarningHandler (1138B78h)]
if (NILP (specified_data))
01074161 cmp esi,dword ptr [_Qnil (1108D6Ch)]
01074167 jne tiff_load+0AEh (10741C5h)
{
/* Read from a file */
file = x_find_image_file (specified_file);
01074169 push dword ptr [specified_file]
0107416C call x_find_image_file (10706E5h)
01074171 pop ecx
if (!STRINGP (file))
01074172 mov ecx,eax
01074174 and ecx,0E0000000h
0107417A cmp ecx,60000000h
01074180 mov dword ptr [buf],eax
01074183 je tiff_load+81h (1074198h)
{
image_error ("Cannot find image file `%s'", specified_file, Qnil);
01074185 push dword ptr [_Qnil (1108D6Ch)]
0107418B push dword ptr [specified_file]
0107418E push offset string "Cannot find image file `%s'" (1166718h)
UNGCPRO;
return 0;
01074193 jmp tiff_load+11Ah (1074231h)
}
/* Try to open the image file. */
tiff = fn_TIFFOpen (SDATA (file), "r");
01074198 push offset string "r" (115F1E0h)
0107419D and eax,1FFFFFFFh
010741A2 push dword ptr [eax+0Ch]
010741A5 call dword ptr [_fn_TIFFOpen (1138AC0h)]
010741AB mov esi,eax
if (tiff == NULL)
010741AD cmp esi,edi
010741AF jne tiff_load+129h (1074240h)
{
image_error ("Cannot open `%s'", file, Qnil);
010741B5 push dword ptr [_Qnil (1108D6Ch)]
010741BB push dword ptr [buf]
010741BE push offset string "Cannot open `%s'" (1166DA4h)
UNGCPRO;
return 0;
010741C3 jmp tiff_load+11Ah (1074231h)
}
}
else
{
/* Memory source! */
memsrc.bytes = SDATA (specified_data);
010741C5 mov eax,esi
010741C7 and eax,1FFFFFFFh
010741CC mov ecx,dword ptr [eax+0Ch]
010741CF mov dword ptr [memsrc],ecx
memsrc.len = SBYTES (specified_data);
010741D2 mov ecx,dword ptr [eax+4]
010741D5 cmp ecx,edi
010741D7 jge tiff_load+0C9h (10741E0h)
010741D9 mov eax,dword ptr [eax]
010741DB mov dword ptr [ebp-20h],eax
010741DE jmp tiff_load+0CCh (10741E3h)
010741E0 mov dword ptr [ebp-20h],ecx
memsrc.index = 0;
tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
(TIFFReadWriteProc) tiff_read_from_memory,
(TIFFReadWriteProc) tiff_write_from_memory,
tiff_seek_in_memory,
tiff_close_memory,
tiff_size_of_memory,
tiff_mmap_memory,
tiff_unmap_memory);
010741E3 push offset tiff_unmap_memory (10723ACh)
010741E8 push offset tiff_mmap_memory (10723A9h)
010741ED push offset tiff_size_of_memory (10723ADh)
010741F2 push offset tiff_close_memory (10723A6h)
010741F7 push offset tiff_seek_in_memory (107236Fh)
010741FC push offset tiff_write_from_memory (107236Bh)
01074201 push offset tiff_read_from_memory (1072335h)
01074206 lea eax,[memsrc]
01074209 push eax
0107420A push offset string "r" (115F1E0h)
0107420F push offset string "memory_source" (1166DFCh)
01074214 mov dword ptr [ebp-1Ch],edi
01074217 call dword ptr [_fn_TIFFClientOpen (1138B00h)]
0107421D mov esi,eax
if (!tiff)
0107421F cmp esi,edi
01074221 jne tiff_load+129h (1074240h)
{
image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
01074223 push dword ptr [_Qnil (1108D6Ch)]
01074229 push dword ptr [ebx+28h]
0107422C push offset string "Cannot open memory source for
`%"... (1166DD8h)
01074231 call add_to_log (1035C57h)
01074236 add esp,0Ch
UNGCPRO;
return 0;
01074239 xor eax,eax
0107423B jmp tiff_load+272h (1074389h)
}
}
/* Get width and height of the image, and allocate a raster buffer
of width x height 32-bit values. */
fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
01074240 lea eax,[width]
01074243 push eax
01074244 push 100h
01074249 push esi
0107424A call dword ptr [_fn_TIFFGetField (1138B2Ch)]
fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
01074250 lea eax,[height]
01074253 push eax
01074254 push 101h
01074259 push esi
0107425A call dword ptr [_fn_TIFFGetField (1138B2Ch)]
buf = (uint32 *) xmalloc (width * height * sizeof *buf);
01074260 mov eax,dword ptr [height]
01074263 imul eax,dword ptr [width]
01074267 shl eax,2
0107426A push eax
0107426B call xmalloc (10070AFh)
01074270 pop ecx
rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
01074271 push edi
01074272 push eax
01074273 push dword ptr [height]
01074276 mov dword ptr [buf],eax
01074279 push dword ptr [width]
0107427C push esi
0107427D call dword ptr [_fn_TIFFReadRGBAImage (1138B90h)]
fn_TIFFClose (tiff);
01074283 push esi
01074284 mov dword ptr [specified_file],eax
01074287 call dword ptr [_fn_TIFFClose (1138AECh)]
if (!rc)
0107428D cmp dword ptr [specified_file],edi
01074290 jne tiff_load+198h (10742AFh)
{
image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
01074292 push dword ptr [_Qnil (1108D6Ch)]
01074298 push dword ptr [ebx+28h]
0107429B push offset string "Error reading TIFF image `%s'" (1166DB8h)
010742A0 call add_to_log (1035C57h)
010742A5 add esp,0Ch
010742A8 xor esi,esi
010742AA jmp tiff_load+267h (107437Eh)
xfree (buf);
UNGCPRO;
return 0;
}
/* Create the X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
010742AF lea eax,[ebx+4]
010742B2 push eax
010742B3 push dword ptr [height]
010742B6 lea esi,[specified_file]
010742B9 push dword ptr [width]
010742BC xor eax,eax
010742BE push dword ptr [f]
010742C1 call x_create_x_image_and_pixmap (1072AE6h)
010742C6 add esp,10h
010742C9 test eax,eax
010742CB je tiff_load+191h (10742A8h)
{
xfree (buf);
UNGCPRO;
return 0;
}
/* Initialize the color table. */
init_color_table ();
/* Process the pixel raster. Origin is in the lower-left corner. */
for (y = 0; y < height; ++y)
010742CD mov dword ptr [y],edi
010742D0 mov edi,dword ptr [height]
010742D3 test edi,edi
010742D5 jle tiff_load+224h (107433Bh)
{
uint32 *row = buf + y * width;
010742D7 mov eax,dword ptr [y]
010742DA imul eax,dword ptr [width]
010742DE mov ecx,dword ptr [buf]
for (x = 0; x < width; ++x)
010742E1 xor esi,esi
010742E3 cmp dword ptr [width],esi
010742E6 lea eax,[ecx+eax*4]
010742E9 mov dword ptr [row],eax
010742EC jle tiff_load+21Ch (1074333h)
{
uint32 abgr = row[x];
010742EE mov eax,dword ptr [row]
010742F1 mov eax,dword ptr [eax+esi*4]
int r = TIFFGetR (abgr) << 8;
int g = TIFFGetG (abgr) << 8;
int b = TIFFGetB (abgr) << 8;
XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
010742F4 mov ecx,eax
010742F6 shr ecx,10h
010742F9 xor edx,edx
010742FB mov dh,cl
010742FD mov ecx,eax
010742FF shr ecx,8
01074302 xor ebx,ebx
01074304 mov bh,cl
01074306 xor ecx,ecx
01074308 mov ch,al
0107430A mov eax,edx
0107430C push ecx
0107430D mov ecx,ebx
0107430F call lookup_rgb_color (10718CDh)
01074314 sub edi,dword ptr [y]
01074317 mov ebx,eax
01074319 dec edi
0107431A push edi
0107431B mov edi,dword ptr [specified_file]
0107431E push esi
0107431F call XPutPixel (10719CBh)
01074324 mov edi,dword ptr [height]
01074327 add esp,0Ch
0107432A inc esi
0107432B cmp esi,dword ptr [width]
0107432E jl tiff_load+1D7h (10742EEh)
for (x = 0; x < width; ++x)
01074330 mov ebx,dword ptr [img]
{
xfree (buf);
UNGCPRO;
return 0;
}
/* Initialize the color table. */
init_color_table ();
/* Process the pixel raster. Origin is in the lower-left corner. */
for (y = 0; y < height; ++y)
01074333 inc dword ptr [y]
01074336 cmp dword ptr [y],edi
01074339 jl tiff_load+1C0h (10742D7h)
}
}
#ifdef COLOR_TABLE_SUPPORT
/* Remember the colors allocated for the image. Free the color table. */
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
#endif /* COLOR_TABLE_SUPPORT */
img->width = width;
0107433B mov eax,dword ptr [width]
img->height = height;
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
0107433E mov ecx,dword ptr [ebx+28h]
01074341 mov dword ptr [ebx+1Ch],eax
01074344 mov dword ptr [ebx+20h],edi
01074347 push 0
01074349 push dword ptr [_QCbackground (1141828h)]
0107434F call image_spec_value (106FF15h)
01074354 cmp eax,dword ptr [_Qnil (1108D6Ch)]
0107435A pop ecx
0107435B pop ecx
0107435C jne tiff_load+25Ch (1074373h)
IMAGE_BACKGROUND (img, f, ximg);
0107435E test byte ptr [ebx+18h],2
01074362 jne tiff_load+25Ch (1074373h)
01074364 push dword ptr [specified_file]
01074367 push dword ptr [f]
0107436A push ebx
0107436B call image_background (107012Ah)
01074370 add esp,0Ch
/* Put the image into the pixmap, then free the X image and its buffer. */
x_put_x_image (f, ximg, img->pixmap, width, height);
x_destroy_x_image (ximg);
01074373 mov eax,dword ptr [specified_file]
01074376 call x_destroy_x_image (10706D5h)
0107437B xor esi,esi
0107437D inc esi
xfree (buf);
0107437E push dword ptr [buf]
01074381 call xfree (1007174h)
01074386 pop ecx
UNGCPRO;
return 1;
01074387 mov eax,esi
01074389 pop edi
0107438A pop esi
0107438B pop ebx
}
0107438C leave
0107438D ret
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-19 19:31 ` Juanma Barranquero
@ 2005-05-19 19:32 ` Juanma Barranquero
2005-05-20 7:20 ` Eli Zaretskii
1 sibling, 0 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-19 19:32 UTC (permalink / raw)
> Yes. If, immediately before the POP EBX, I manually restore the stack
> to the value it had after the PUSH EBX at the start of the routine,
I meant: "Immediately before POP EDI, to the value it had after PUSH EDI."
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-19 19:31 ` Juanma Barranquero
2005-05-19 19:32 ` Juanma Barranquero
@ 2005-05-20 7:20 ` Eli Zaretskii
2005-05-20 8:24 ` Kim F. Storm
1 sibling, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-20 7:20 UTC (permalink / raw)
Cc: emacs-devel
> Date: Thu, 19 May 2005 21:31:23 +0200
> From: Juanma Barranquero <lekktu@gmail.com>
>
> But I don't think is an error in MSVC. I think it's some mixup between
> "pascal" and "C" style calls (as you know, the former remove their
> arguments, the latter don't). MSVC must be thinking that the external
> TIFF functions do remove their arguments, so it is not doing it.
> Sounds like an issue with the external declarations on the header
> files.
Can you show the declarations of the TIFF functions as they appear in
the header files visible to MSVC when it compiles Emacs?
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 7:20 ` Eli Zaretskii
@ 2005-05-20 8:24 ` Kim F. Storm
2005-05-20 10:01 ` Eli Zaretskii
2005-05-20 10:16 ` Jason Rumney
0 siblings, 2 replies; 37+ messages in thread
From: Kim F. Storm @ 2005-05-20 8:24 UTC (permalink / raw)
Cc: Juanma Barranquero, emacs-devel
"Eli Zaretskii" <eliz@gnu.org> writes:
>> Date: Thu, 19 May 2005 21:31:23 +0200
>> From: Juanma Barranquero <lekktu@gmail.com>
>>
>> But I don't think is an error in MSVC. I think it's some mixup between
>> "pascal" and "C" style calls (as you know, the former remove their
>> arguments, the latter don't). MSVC must be thinking that the external
>> TIFF functions do remove their arguments, so it is not doing it.
>> Sounds like an issue with the external declarations on the header
>> files.
>
> Can you show the declarations of the TIFF functions as they appear in
> the header files visible to MSVC when it compiles Emacs?
Could it be that the following define need to specify "Pascal" somewhere
for the tiff library?
#define DEF_IMGLIB_FN(func) FARPROC fn_##func
--
Kim F. Storm <storm@cua.dk> http://www.cua.dk
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 8:24 ` Kim F. Storm
@ 2005-05-20 10:01 ` Eli Zaretskii
2005-05-20 10:16 ` Jason Rumney
1 sibling, 0 replies; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-20 10:01 UTC (permalink / raw)
Cc: lekktu, emacs-devel
> Cc: Juanma Barranquero <lekktu@gmail.com>, emacs-devel@gnu.org
> From: storm@cua.dk (Kim F. Storm)
> Date: Fri, 20 May 2005 10:24:55 +0200
>
> Could it be that the following define need to specify "Pascal" somewhere
> for the tiff library?
>
> #define DEF_IMGLIB_FN(func) FARPROC fn_##func
I think it should be something else. First, from Juanma's
investigations it looks like MSVC already thinks those functions use
the Pascal ABI. Second, the MinGW compiler does produce correct code,
so the fix should be only for MSVC (perhaps some preprocessor macro
works for GCC, but not MSVC). And third, I think the right qualifiers
are __stdcall vs __cdecl, not "Pascal".
I asked to see the relevant fragments from libtiff headers used during
the compilation so that we could figure out what goes wrong there.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 8:24 ` Kim F. Storm
2005-05-20 10:01 ` Eli Zaretskii
@ 2005-05-20 10:16 ` Jason Rumney
2005-05-20 10:42 ` Juanma Barranquero
2005-05-20 12:19 ` Benjamin Riefenstahl
1 sibling, 2 replies; 37+ messages in thread
From: Jason Rumney @ 2005-05-20 10:16 UTC (permalink / raw)
Cc: Juanma Barranquero, Eli Zaretskii, emacs-devel
Kim F. Storm wrote:
>"Eli Zaretskii" <eliz@gnu.org> writes:
>
>
>
>>Can you show the declarations of the TIFF functions as they appear in
>>the header files visible to MSVC when it compiles Emacs?
>>
>>
>
>Could it be that the following define need to specify "Pascal" somewhere
>for the tiff library?
>
>#define DEF_IMGLIB_FN(func) FARPROC fn_##func
>
>
The version of TIFF headers I have uses extern "C" if compiling under
C++, so I doubt the library is using Pascal calling conventions.
Maybe Juanma's library is different than mine.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 10:16 ` Jason Rumney
@ 2005-05-20 10:42 ` Juanma Barranquero
2005-05-20 14:44 ` Eli Zaretskii
2005-05-20 12:19 ` Benjamin Riefenstahl
1 sibling, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-20 10:42 UTC (permalink / raw)
> The version of TIFF headers I have uses extern "C" if compiling under
> C++, so I doubt the library is using Pascal calling conventions.
> Maybe Juanma's library is different than mine.
Unless I'm wrong, the issue is not how the functions are defined on
the headers, because we don't statically link against the functions,
but how are they compiled in the library and how do we define the
fn_XXX pointers to them. In this case, the GnuWin32 TIFF 3.7.2
libraries seem to be compiled to use C calling conventions, but we
declare pointers to them with DEF_IMGLIB_FN, which says unequivocally
that they're FARPROC (i.e, "pascal").
Defining
typedef int (FAR CDECL *CFARPROC)();
#define DEF_IMGLIB_FNC(func) CFARPROC fn_##func
and using DEF_IMGLIB_FNC for the Tiff functions works.
The TIFF page in gnuwin32.sourceforge.net says:
"The GnuWin32 distribution comes in two versions. The ordinary version
uses the standard Unix equivalents, such as fopen and read, for input
and output, the other version (Tiff-win32) uses the Win32 API
functions, such as CreateFile and ReadFile, for input and output. The
ordinary version (Tiff) is more suitable for porting Unix programs,
the Win32-API version is more suitable for writing Win32 programs."
However, I'm getting the same results (problems, I mean) with the
standard and the Win32 versions.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 10:16 ` Jason Rumney
2005-05-20 10:42 ` Juanma Barranquero
@ 2005-05-20 12:19 ` Benjamin Riefenstahl
1 sibling, 0 replies; 37+ messages in thread
From: Benjamin Riefenstahl @ 2005-05-20 12:19 UTC (permalink / raw)
Cc: emacs-devel
Hi Jason,
Jason Rumney writes:
> The version of TIFF headers I have uses extern "C" if compiling
> under C++, so I doubt the library is using Pascal calling
> conventions. Maybe Juanma's library is different than mine.
'extern "C"' doesn't mean what you think it means, at least not in
most compilers.
In theory 'extern "<Language>"' is the C++ equivalent of the
propriatory '__cdecl', '__stdcall' and '__pascal' keywords known from
the C compilers. But the exact behaviour of that C++ feature is
implementation defined, especially for languages other than "C".
In practice with MSC++ and GCC, '__stdcall' and 'extern "C"' are
*both* needed (or at least it's highly recommended to use both) in C++
mode to actually get '__stdcall' calling conventions and name
mangling.
benny
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 10:42 ` Juanma Barranquero
@ 2005-05-20 14:44 ` Eli Zaretskii
2005-05-20 15:46 ` Jason Rumney
2005-05-20 16:29 ` Juanma Barranquero
0 siblings, 2 replies; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-20 14:44 UTC (permalink / raw)
Cc: emacs-devel
> Date: Fri, 20 May 2005 12:42:09 +0200
> From: Juanma Barranquero <lekktu@gmail.com>
>
> Unless I'm wrong, the issue is not how the functions are defined on
> the headers, because we don't statically link against the functions,
> but how are they compiled in the library and how do we define the
> fn_XXX pointers to them.
It's the issue with both: the prototypes in the header files should be
consistent with how the functions were compiled, since those
prototypes are the only way for the compiler to know how the functions
were compiled. If it doesn't know that, it might produce wrong code.
> In this case, the GnuWin32 TIFF 3.7.2
> libraries seem to be compiled to use C calling conventions, but we
> declare pointers to them with DEF_IMGLIB_FN, which says unequivocally
> that they're FARPROC (i.e, "pascal").
That seems to be the problem. What I still don't get is how come the
same declaration that uses FARPROC works for the MinGW build? Can you
figure this out?
If we know this, we could fix the DEF_IMGLIB_FN macro so that it does
TRT for both compilers, e.g., by using __MINGW__ condition.
> The TIFF page in gnuwin32.sourceforge.net says:
>
> "The GnuWin32 distribution comes in two versions. The ordinary version
> uses the standard Unix equivalents, such as fopen and read, for input
> and output, the other version (Tiff-win32) uses the Win32 API
> functions, such as CreateFile and ReadFile, for input and output. The
> ordinary version (Tiff) is more suitable for porting Unix programs,
> the Win32-API version is more suitable for writing Win32 programs."
This doesn't say anything about the calling conventions, just about
the inner workings of the functions. So I'm not surprised that both
versions have the same effect.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 14:44 ` Eli Zaretskii
@ 2005-05-20 15:46 ` Jason Rumney
2005-05-20 15:52 ` Eli Zaretskii
2005-05-20 16:31 ` Juanma Barranquero
2005-05-20 16:29 ` Juanma Barranquero
1 sibling, 2 replies; 37+ messages in thread
From: Jason Rumney @ 2005-05-20 15:46 UTC (permalink / raw)
Cc: Juanma Barranquero, emacs-devel
Eli Zaretskii wrote:
>That seems to be the problem. What I still don't get is how come the
>same declaration that uses FARPROC works for the MinGW build? Can you
>figure this out?
>
>
Without looking at the disassembly, I'd guess that MinGW gcc and
non-optimised MSVC builds restore the stack pointer from a known
location regardless of the calling convention, which should always work.
>If we know this, we could fix the DEF_IMGLIB_FN macro so that it does
>TRT for both compilers, e.g., by using __MINGW__ condition.
>
>
I think TRT will not depend on __MINGW__. Mingw works despite there
being a bug, not because of it.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 15:46 ` Jason Rumney
@ 2005-05-20 15:52 ` Eli Zaretskii
2005-05-20 16:33 ` Juanma Barranquero
2005-05-20 16:31 ` Juanma Barranquero
1 sibling, 1 reply; 37+ messages in thread
From: Eli Zaretskii @ 2005-05-20 15:52 UTC (permalink / raw)
Cc: lekktu, emacs-devel
> Date: Fri, 20 May 2005 16:46:38 +0100
> From: Jason Rumney <jasonr@gnu.org>
> CC: Juanma Barranquero <lekktu@gmail.com>, emacs-devel@gnu.org
>
> Without looking at the disassembly, I'd guess that MinGW gcc and
> non-optimised MSVC builds restore the stack pointer from a known
> location regardless of the calling convention, which should always work.
>
>
> >If we know this, we could fix the DEF_IMGLIB_FN macro so that it does
> >TRT for both compilers, e.g., by using __MINGW__ condition.
> >
> >
> I think TRT will not depend on __MINGW__. Mingw works despite there
> being a bug, not because of it.
So you are saying that MinGW works simply because it doesn't optimize
as well as MSVC, yes? That could be it, but I'd prefer that someone
looks at the code produced by MinGW and see that it indeed doesn't
restore the stack pointer, either.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 14:44 ` Eli Zaretskii
2005-05-20 15:46 ` Jason Rumney
@ 2005-05-20 16:29 ` Juanma Barranquero
1 sibling, 0 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-20 16:29 UTC (permalink / raw)
> It's the issue with both: the prototypes in the header files should be
> consistent with how the functions were compiled, since those
> prototypes are the only way for the compiler to know how the functions
> were compiled. If it doesn't know that, it might produce wrong code.
Yes, in general, for static linking (either with static libraries, or
with stubs to dynamic ones). But in this case, MSVC is not
compiling/liking statically against any function as defined in the
header. There are no TIFF functions, as far as it knows, just a bunch
of variables of type FARPROC that we're assigning and calling, so
whether there's
FAR CDECL TIFFOpen(...);
or
FARPROC TIFFOpen(...);
on the header should be irrelevant. MSVC knows nothing about TIFFOpen;
it just knows there's a variable fn_TIFFOpen which gets initialized
with a call to GetProcAddress() and called afterwards. And it's the
type of fn_TIFFOpen which counts.
> That seems to be the problem. What I still don't get is how come the
> same declaration that uses FARPROC works for the MinGW build? Can you
> figure this out?
Perhaps Jason's right and the bug is just not noticeable.
Think of this: if lookup_image didn't use a temporary variable that
gets assigned to a register and accidentally clobbered by tiff_load,
we wouldn't see the problem with MSVC either.
> This doesn't say anything about the calling conventions, just about
> the inner workings of the functions. So I'm not surprised that both
> versions have the same effect.
Well, I hoped that the Win32 version would use the more common
convention for DLL exports on Windows (that is, pascal). But it
doesn't.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 15:46 ` Jason Rumney
2005-05-20 15:52 ` Eli Zaretskii
@ 2005-05-20 16:31 ` Juanma Barranquero
1 sibling, 0 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-20 16:31 UTC (permalink / raw)
> Without looking at the disassembly, I'd guess that MinGW gcc and
> non-optimised MSVC builds restore the stack pointer from a known
> location regardless of the calling convention, which should always work.
Optimized MSVC builds also restore the stack and frame pointers. But
before that it tries to pop local registers saved on the stack. Bingo!
My guess (but I've not compiled un-optimized to test it) is that
non-optimized MSVC builds work because the compiler is reloading
variables and/or being much less aggresive in caching values on
registers.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 15:52 ` Eli Zaretskii
@ 2005-05-20 16:33 ` Juanma Barranquero
2005-05-20 17:57 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-20 16:33 UTC (permalink / raw)
> That could be it, but I'd prefer that someone
> looks at the code produced by MinGW and see that it indeed doesn't
> restore the stack pointer, either.
I've not had much luck trying to build with MinGW, so I won't be able
to test it. Jason, could you perhaps try it?
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 16:33 ` Juanma Barranquero
@ 2005-05-20 17:57 ` Juanma Barranquero
2005-05-21 10:21 ` Jason Rumney
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-20 17:57 UTC (permalink / raw)
With the single change from
#define DEF_IMGLIB_FN(func) FARPROC fn_##func
to
#define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
all test images I have do work beautifully.
MORE IMPORTANT: two horrible hacks that I added about a year ago (when
I first fought this same issue and came to the wrong conclusion) to
keep Emacs from crashing CAN BE REMOVED!
So I'd say this is probably the right answer. I've commited the
changes so people with MinGW builds can test them.
If this works for them, today will be a happy day indeed :)
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-20 17:57 ` Juanma Barranquero
@ 2005-05-21 10:21 ` Jason Rumney
2005-05-21 10:33 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Jason Rumney @ 2005-05-21 10:21 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
> With the single change from
>
> #define DEF_IMGLIB_FN(func) FARPROC fn_##func
>
> to
>
> #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
>
> all test images I have do work beautifully.
If the other image libraries we use also use C calling conventions,
then that is the correct fix, I think.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-21 10:21 ` Jason Rumney
@ 2005-05-21 10:33 ` Juanma Barranquero
2005-05-21 21:13 ` Jason Rumney
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-21 10:33 UTC (permalink / raw)
Cc: emacs-devel
> If the other image libraries we use also use C calling conventions,
> then that is the correct fix, I think.
I confess I've not taken the time to check whether all the GnuWin32
libraries do use C calling conventions, but I've tested all kind of
images with that fix, and they worked. That suggest they really do use
C calling conventions; calling a C-style function as a Pascal one can
get obscured by the fact that functions do reset the frame and stack
pointers upon returning, but calling a Pascal-style function as a C
one would remove too many things from the stack and it would crash on
the next RET...
However, and in the interest of peace of mind, I'll trace the
functions and see that they're really doing what I think :)
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-21 10:33 ` Juanma Barranquero
@ 2005-05-21 21:13 ` Jason Rumney
2005-05-22 21:21 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Jason Rumney @ 2005-05-21 21:13 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
>> If the other image libraries we use also use C calling conventions,
>> then that is the correct fix, I think.
>
> However, and in the interest of peace of mind, I'll trace the
> functions and see that they're really doing what I think :)
Studying the headers, png and jpeg explicitly use _cdecl (or __cdecl
depending on compiler), while xpm and gif specify nothing (so will
default to _cdecl). So the fix you suggested is correct, I think.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-21 21:13 ` Jason Rumney
@ 2005-05-22 21:21 ` Juanma Barranquero
2005-06-03 12:08 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-05-22 21:21 UTC (permalink / raw)
> Studying the headers, png and jpeg explicitly use _cdecl (or __cdecl
> depending on compiler), while xpm and gif specify nothing (so will
> default to _cdecl).
Yeah. And they indeed do use "ret" and not "ret n".
> So the fix you suggested is correct, I think.
Cool. So, for the first time, the image support on MSVC builds is as
stable as on MinGW builds.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-05-22 21:21 ` Juanma Barranquero
@ 2005-06-03 12:08 ` Juanma Barranquero
2005-06-03 13:06 ` David Kastrup
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-06-03 12:08 UTC (permalink / raw)
> Cool. So, for the first time, the image support on MSVC builds is as
> stable as on MinGW builds.
Well, I spoke too soon.
I have another problem with image support on MSVC builds. It is,
AFAICS, unrelated to the previous problem with the calling convention
of the libraries.
Doing
(insert-image-file "c:/image/test/myimage.png")
works, at works C-o from dired. However, either one of:
(insert-image (create-image "c:/image/test/myimage.png"))
(put-image (create-image "c:/image/test/myimage.png") 0)
crashes. In other words: png_load, and jpeg_load, die an horrible death from:
(image :type xxx :file "...")
but they have no trouble with
(image :type xxx :data "...")
png_load, for example, dies at the call to
fn_png_read_info (png_ptr, info_ptr);
on png_load, while jpeg_load dies at:
fn_jpeg_read_header (&cinfo, 1);
Any clues about what can be happening?
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-03 12:08 ` Juanma Barranquero
@ 2005-06-03 13:06 ` David Kastrup
2005-06-03 15:28 ` jasonr
2005-06-05 0:44 ` Juanma Barranquero
0 siblings, 2 replies; 37+ messages in thread
From: David Kastrup @ 2005-06-03 13:06 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
>> Cool. So, for the first time, the image support on MSVC builds is as
>> stable as on MinGW builds.
>
> Well, I spoke too soon.
>
> I have another problem with image support on MSVC builds. It is,
> AFAICS, unrelated to the previous problem with the calling convention
> of the libraries.
>
> Doing
>
> (insert-image-file "c:/image/test/myimage.png")
>
> works, at works C-o from dired. However, either one of:
>
> (insert-image (create-image "c:/image/test/myimage.png"))
> (put-image (create-image "c:/image/test/myimage.png") 0)
>
> crashes. In other words: png_load, and jpeg_load, die an horrible death from:
>
> (image :type xxx :file "...")
>
> but they have no trouble with
>
> (image :type xxx :data "...")
>
> png_load, for example, dies at the call to
>
> fn_png_read_info (png_ptr, info_ptr);
>
> on png_load, while jpeg_load dies at:
>
> fn_jpeg_read_header (&cinfo, 1);
>
> Any clues about what can be happening?
The files are not opened in binary mode or something like that?
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-03 13:06 ` David Kastrup
@ 2005-06-03 15:28 ` jasonr
2005-06-03 17:23 ` Stefan Monnier
2005-06-05 0:44 ` Juanma Barranquero
1 sibling, 1 reply; 37+ messages in thread
From: jasonr @ 2005-06-03 15:28 UTC (permalink / raw)
Cc: Juanma Barranquero, emacs-devel
Quoting David Kastrup <dak@gnu.org>:
> The files are not opened in binary mode or something like that?
Its a possibility, but Emacs should be linked with binmode.obj, which makes the
default mode binary.
If the link with binmode.obj fails and default is text mode for some reason (as
happened with certain versions of MingW for 21.4 and earlier), we usually get
crashes loading .elc files either during startup or when opening custom
buffers.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-03 15:28 ` jasonr
@ 2005-06-03 17:23 ` Stefan Monnier
0 siblings, 0 replies; 37+ messages in thread
From: Stefan Monnier @ 2005-06-03 17:23 UTC (permalink / raw)
Cc: Juanma Barranquero, emacs-devel
>> The files are not opened in binary mode or something like that?
> Its a possibility, but Emacs should be linked with binmode.obj, which
> makes the default mode binary.
Also opening them in the wrong mode should only cause garbled images,
not crashes, right?
Stefan
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-03 13:06 ` David Kastrup
2005-06-03 15:28 ` jasonr
@ 2005-06-05 0:44 ` Juanma Barranquero
2005-06-06 11:26 ` Juanma Barranquero
1 sibling, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-06-05 0:44 UTC (permalink / raw)
On 6/3/05, David Kastrup <dak@gnu.org> wrote:
> The files are not opened in binary mode or something like that?
First thing I thought, but:
/* Open the image file. */
fp = fopen (SDATA (file), "rb");
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-05 0:44 ` Juanma Barranquero
@ 2005-06-06 11:26 ` Juanma Barranquero
2005-06-14 2:02 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-06-06 11:26 UTC (permalink / raw)
Funnier and funnier.
I've been able to compile an MSVC debug release of libpng13; with it,
both the MSVC and the GCC builds of Emacs crash.
It happens inside msvcr71d.dll; (part of) the stack is:
ntdll.dll!7c928fea()
ntdll.dll!7c91104b()
msvcr71d.dll!_lock_file(void * pf=0x77c2fce0) Line 236 C
> msvcr71d.dll!fread(void * buffer=0x0082e268, unsigned int
size=0x00000001, unsigned int count=0x00000004, _iobuf *
stream=0x77c2fce0) Line 75 + 0x9 C
libpng13d.dll!png_default_read_data(png_struct_def *
png_ptr=0x20844540, unsigned char * data=0x0082e268, unsigned int
length=0x00000004) Line 55 + 0x19 C
libpng13d.dll!png_read_data(png_struct_def * png_ptr=0x20844540,
unsigned char * data=0x0082e268, unsigned int length=0x00000004) Line
31 + 0x14 C
libpng13d.dll!png_read_info(png_struct_def * png_ptr=0x20844540,
png_info_struct * info_ptr=0x208483e0) Line 402 + 0xf C
The crash is on the _lock_file() call inside the msvcr71
implementation of fread(); the relevant code is:
void __cdecl _lock_file (
void *pf
)
{
/*
* The way the FILE (pointed to by pf) is locked depends on whether
* it is part of _iob[] or not
*/
if ( (pf >= (void *)_iob) && (pf <= (void *)(&_iob[_IOB_ENTRIES-1])) )
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
*/
_lock( _STREAM_LOCKS + (int)((FILE *)pf - _iob) );
else
/*
* Not part of _iob[]. Therefore, *pf is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
EnterCriticalSection( &(((_FILEX *)pf)->lock) );
}
The code decides that the FILE * is not part of _iob[] and calls
EnterCriticalSection, which gets an access violation writing on
0x00000010.
(I suppose I could get around the issue by writing read functions for
libpng and jpeg and bypassing the standard code altogether; still,
it'd be great to understand what's happening.)
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-06 11:26 ` Juanma Barranquero
@ 2005-06-14 2:02 ` Juanma Barranquero
2005-06-14 7:32 ` David Kastrup
0 siblings, 1 reply; 37+ messages in thread
From: Juanma Barranquero @ 2005-06-14 2:02 UTC (permalink / raw)
> (I suppose I could get around the issue by writing read functions for
> libpng and jpeg and bypassing the standard code altogether;
And finally, that's what I've done.
The following patch gets rid of png_init_io() and jpeg_stdio_src(),
and instead define custom read functions to read image data from FILE
*. With it, image support finally works as expected on MSVC and MinGW
builds of Emacs on Windows.
Highlights of the patch:
- It has no ChangeLog entries :-) (I'll write them once the patch is accepted)
- Deletion of png_init_io() and jpeg_stdio_src() is not conditional
on HAVE_NTGUI; I've assumed it's best to have just one mechanism for
Windows, Unix, GNU/Linux and MacOS platforms. I can reinstate the
deleted functions and put the alternative into #ifdef's if deemed
necessary.
- I've changed a few names of the memory-reading data source
functions for JPEG so it's clearer the paralelism between from-memory
and from-file data source setups.
- Most jpeg code I've added is heavily based on jdatasrc.c, from the
JPEG library. I assume there's no legal trouble, as other jpeg code
comes also from JPEG library examples.
--
/L/e/k/t/u
Index: src/image.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/image.c,v
retrieving revision 1.27
diff -u -2 -r1.27 image.c
--- src/image.c 11 Jun 2005 16:24:36 -0000 1.27
+++ src/image.c 14 Jun 2005 01:46:10 -0000
@@ -5632,5 +5632,4 @@
DEF_IMGLIB_FN (png_destroy_read_struct);
DEF_IMGLIB_FN (png_set_read_fn);
-DEF_IMGLIB_FN (png_init_io);
DEF_IMGLIB_FN (png_set_sig_bytes);
DEF_IMGLIB_FN (png_read_info);
@@ -5664,5 +5663,4 @@
LOAD_IMGLIB_FN (library, png_destroy_read_struct);
LOAD_IMGLIB_FN (library, png_set_read_fn);
- LOAD_IMGLIB_FN (library, png_init_io);
LOAD_IMGLIB_FN (library, png_set_sig_bytes);
LOAD_IMGLIB_FN (library, png_read_info);
@@ -5690,5 +5688,4 @@
#define fn_png_destroy_read_struct png_destroy_read_struct
#define fn_png_set_read_fn png_set_read_fn
-#define fn_png_init_io png_init_io
#define fn_png_set_sig_bytes png_set_sig_bytes
#define fn_png_read_info png_read_info
@@ -5763,4 +5760,21 @@
+/* Function set as reader function when reading PNG image from a file.
+ PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
+ bytes from the input to DATA. */
+
+static void
+png_read_from_file (png_ptr, data, length)
+ png_structp png_ptr;
+ png_bytep data;
+ png_size_t length;
+{
+ FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
+
+ if (fread (data, 1, length, fp) < length)
+ fn_png_error (png_ptr, "Read error");
+}
+
+
/* Load PNG image IMG for use on frame F. Value is non-zero if
successful. */
@@ -5896,5 +5910,5 @@
fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
else
- fn_png_init_io (png_ptr, fp);
+ fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
fn_png_set_sig_bytes (png_ptr, sizeof sig);
@@ -6295,5 +6309,4 @@
DEF_IMGLIB_FN (jpeg_read_header);
DEF_IMGLIB_FN (jpeg_read_scanlines);
-DEF_IMGLIB_FN (jpeg_stdio_src);
DEF_IMGLIB_FN (jpeg_std_error);
DEF_IMGLIB_FN (jpeg_resync_to_restart);
@@ -6311,5 +6324,4 @@
LOAD_IMGLIB_FN (library, jpeg_start_decompress);
LOAD_IMGLIB_FN (library, jpeg_read_header);
- LOAD_IMGLIB_FN (library, jpeg_stdio_src);
LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
@@ -6337,5 +6349,4 @@
#define fn_jpeg_read_header jpeg_read_header
#define fn_jpeg_read_scanlines jpeg_read_scanlines
-#define fn_jpeg_stdio_src jpeg_stdio_src
#define fn_jpeg_std_error jpeg_std_error
#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
@@ -6359,4 +6370,15 @@
+/* Method to terminate data source. Called by
+ jpeg_finish_decompress() after all data has been processed.
+ Common to memory and file source managers. */
+
+static void
+our_common_term_source (cinfo)
+ j_decompress_ptr cinfo;
+{
+}
+
+
/* Init source method for JPEG data source manager. Called by
jpeg_read_header() before any data is actually read. See
@@ -6364,5 +6386,5 @@
static void
-our_init_source (cinfo)
+our_memory_init_source (cinfo)
j_decompress_ptr cinfo;
{
@@ -6375,5 +6397,5 @@
static boolean
-our_fill_input_buffer (cinfo)
+our_memory_fill_input_buffer (cinfo)
j_decompress_ptr cinfo;
{
@@ -6395,5 +6417,5 @@
static void
-our_skip_input_data (cinfo, num_bytes)
+our_memory_skip_input_data (cinfo, num_bytes)
j_decompress_ptr cinfo;
long num_bytes;
@@ -6412,14 +6434,4 @@
-/* Method to terminate data source. Called by
- jpeg_finish_decompress() after all data has been processed. */
-
-static void
-our_term_source (cinfo)
- j_decompress_ptr cinfo;
-{
-}
-
-
/* Set up the JPEG lib for reading an image from DATA which contains
LEN bytes. CINFO is the decompression info structure created for
@@ -6445,9 +6457,9 @@
src = (struct jpeg_source_mgr *) cinfo->src;
- src->init_source = our_init_source;
- src->fill_input_buffer = our_fill_input_buffer;
- src->skip_input_data = our_skip_input_data;
+ src->init_source = our_memory_init_source;
+ src->fill_input_buffer = our_memory_fill_input_buffer;
+ src->skip_input_data = our_memory_skip_input_data;
src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use
default method. */
- src->term_source = our_term_source;
+ src->term_source = our_common_term_source;
src->bytes_in_buffer = len;
src->next_input_byte = data;
@@ -6455,4 +6467,136 @@
+/* JPEG data source manager setup for JPEG images read from a file.
+ Heavily based on jdatasrc.c from the JPEG library. */
+
+struct my_jpeg_file_src {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ FILE *infile; /* source stream */
+ JOCTET *buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+};
+
+typedef struct my_jpeg_file_src *my_jpeg_file_ptr;
+
+#define JPEG_INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
+
+
+/* Init source method for JPEG data source manager.
+ Called by jpeg_read_header() before any data is actually read. */
+
+static void
+our_file_init_source (j_decompress_ptr cinfo)
+{
+ my_jpeg_file_ptr src = (my_jpeg_file_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = 1;
+}
+
+
+/* Fill input buffer method for JPEG data source manager.
+ Called whenever more data is needed. */
+
+static boolean
+our_file_fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_jpeg_file_ptr src = (my_jpeg_file_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = fread (src->buffer, 1, JPEG_INPUT_BUF_SIZE, src->infile);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT (cinfo, JERR_INPUT_EMPTY);
+ WARNMS (cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = 0;
+
+ return 1;
+}
+
+
+/* Method to skip over NUM_BYTES bytes in the image data.
+ CINFO->src is the JPEG data source manager. */
+
+static void
+our_file_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_jpeg_file_ptr src = (my_jpeg_file_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0)
+ {
+ while (num_bytes > (long) src->pub.bytes_in_buffer)
+ {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) our_file_fill_input_buffer (cinfo);
+ /* note we assume that fill_file_input_buffer will never
return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+
+/* Set up the JPEG lib for reading an image from a FILE * via
+ a customized function, thus avoiding FILE * conflicts between
+ different builds of the image library. CINFO is the
+ decompression info structure created for reading the image. */
+
+static void
+jpeg_file_src (cinfo, infile)
+ j_decompress_ptr cinfo;
+ FILE *infile;
+{
+ my_jpeg_file_ptr src;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL)
+ {
+ /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof (struct my_jpeg_file_src));
+ src = (my_jpeg_file_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ JPEG_INPUT_BUF_SIZE * sizeof (JOCTET));
+ }
+
+ src = (my_jpeg_file_ptr) cinfo->src;
+ src->pub.init_source = our_file_init_source;
+ src->pub.fill_input_buffer = our_file_fill_input_buffer;
+ src->pub.skip_input_data = our_file_skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart_wrapper; /*
use default method */
+ src->pub.term_source = our_common_term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
+
+
/* Load image IMG for use on frame F. Patterned after example.c
from the JPEG lib. */
@@ -6538,5 +6682,5 @@
if (NILP (specified_data))
- fn_jpeg_stdio_src (&cinfo, (FILE *) fp);
+ jpeg_file_src (&cinfo, fp);
else
jpeg_memory_src (&cinfo, SDATA (specified_data),
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-14 2:02 ` Juanma Barranquero
@ 2005-06-14 7:32 ` David Kastrup
2005-06-14 9:15 ` Juanma Barranquero
0 siblings, 1 reply; 37+ messages in thread
From: David Kastrup @ 2005-06-14 7:32 UTC (permalink / raw)
Cc: emacs-devel
Juanma Barranquero <lekktu@gmail.com> writes:
> - Most jpeg code I've added is heavily based on jdatasrc.c, from
> the JPEG library. I assume there's no legal trouble, as other jpeg
> code comes also from JPEG library examples.
The examples are just that: examples. They are supposed to illustrate
the most basic/natural use of the library and so don't contain
copyrightable material unless somebody defined the interface very
badly. You can claim copyright only on passages of sufficient
creative value, and examples often are explicitly exempt (don't know
whether this is the case here).
So you can't judge the viability of taking core code (it sounds to me
like that is what you did) by the viability of following example code.
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Problem with library images on Windows (again)
2005-06-14 7:32 ` David Kastrup
@ 2005-06-14 9:15 ` Juanma Barranquero
0 siblings, 0 replies; 37+ messages in thread
From: Juanma Barranquero @ 2005-06-14 9:15 UTC (permalink / raw)
Cc: emacs-devel
On 6/14/05, David Kastrup <dak@gnu.org> wrote:
> So you can't judge the viability of taking core code (it sounds to me
> like that is what you did) by the viability of following example code.
The code for the memory data source in image.c is already pretty similar.
In any case, I found this bit from install.doc, which sums up the
situation perfectly:
2. Microsoft C cannot pass file pointers between applications and DLLs.
(See Microsoft Knowledge Base, PSS ID Number Q50336.) So jdatasrc.c and
jdatadst.c don't work if you open a file in your application and then pass
the pointer to the DLL. One workaround is to make jdatasrc.c/jdatadst.c
part of your main application rather than part of the DLL.
--
/L/e/k/t/u
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2005-06-14 9:15 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-18 15:53 Problem with library images on Windows (again) Juanma Barranquero
2005-05-18 19:30 ` Andreas Schwab
2005-05-18 22:44 ` Juanma Barranquero
2005-05-19 6:58 ` Jason Rumney
2005-05-18 22:16 ` Jason Rumney
2005-05-18 22:52 ` Juanma Barranquero
2005-05-19 3:50 ` Eli Zaretskii
2005-05-19 8:13 ` Juanma Barranquero
2005-05-19 19:05 ` Eli Zaretskii
2005-05-19 19:31 ` Juanma Barranquero
2005-05-19 19:32 ` Juanma Barranquero
2005-05-20 7:20 ` Eli Zaretskii
2005-05-20 8:24 ` Kim F. Storm
2005-05-20 10:01 ` Eli Zaretskii
2005-05-20 10:16 ` Jason Rumney
2005-05-20 10:42 ` Juanma Barranquero
2005-05-20 14:44 ` Eli Zaretskii
2005-05-20 15:46 ` Jason Rumney
2005-05-20 15:52 ` Eli Zaretskii
2005-05-20 16:33 ` Juanma Barranquero
2005-05-20 17:57 ` Juanma Barranquero
2005-05-21 10:21 ` Jason Rumney
2005-05-21 10:33 ` Juanma Barranquero
2005-05-21 21:13 ` Jason Rumney
2005-05-22 21:21 ` Juanma Barranquero
2005-06-03 12:08 ` Juanma Barranquero
2005-06-03 13:06 ` David Kastrup
2005-06-03 15:28 ` jasonr
2005-06-03 17:23 ` Stefan Monnier
2005-06-05 0:44 ` Juanma Barranquero
2005-06-06 11:26 ` Juanma Barranquero
2005-06-14 2:02 ` Juanma Barranquero
2005-06-14 7:32 ` David Kastrup
2005-06-14 9:15 ` Juanma Barranquero
2005-05-20 16:31 ` Juanma Barranquero
2005-05-20 16:29 ` Juanma Barranquero
2005-05-20 12:19 ` Benjamin Riefenstahl
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.