cause of: AddressSanitizer: SEGV on unknown address (null pointer) - gdb

I need some advice how to identify the source of the segfault.
compiled with ASAN:
==21093==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f09d744d882 bp 0x000000001000 sp 0x62100001c538 T0)
ASAN:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.
started with gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5eeb882 in __memset_avx2_erms () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff5eeb882 in __memset_avx2_erms () from /usr/lib/libc.so.6
#1 0xbebebebebebebebe in ?? ()
#2 0xbebebebebebebebe in ?? ()
...
1. Edit:
the output above was compiled for 64bit (x86_64), on 32bit following output is generated:
==8361==ERROR: AddressSanitizer failed to allocate 0x200000 (2097152) bytes of SizeClassAllocator32 (error code: 12)
==8361==Process memory map follows:
0x00200000-0x00300000
0x00400000-0x00500000
...
0xf7791000-0xf7792000 /lib32/ld-2.24.so
0xf7800000-0xffd00000
0xffe34000-0xffe55000 [stack]
==8361==End of process memory map.
==8361==AddressSanitizer CHECK failed: ../../../../../src/libsanitizer/sanitizer_common/sanitizer_common.cc:180 "((0 && "unable to mmap")) != (0)" (0x0, 0x0)
ERROR: Failed to mmap
2. EDIT:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5eeb882 in __memset_avx2_erms () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff5eeb882 in __memset_avx2_erms () from /usr/lib/libc.so.6
#1 0xbebebebebebebebe in ?? ()
#2 0xbebebebebebebebe in ?? ()
#3 0xbebebebebebebebe in ?? ()
#4 0xbebebebebebebebe in ?? ()
...
(gdb) record instruction-history
17798 0x00007ffff5eeb8b6 <__memset_avx2_unaligned_erms+22>: cmp $0x40,%rdx
17799 0x00007ffff5eeb8ba <__memset_avx2_unaligned_erms+26>: ja 0x7ffff5eeb8ca <__memset_avx2_unaligned_erms+42>
17800 0x00007ffff5eeb8ca <__memset_avx2_unaligned_erms+42>: cmp $0x800,%rdx
17801 0x00007ffff5eeb8d1 <__memset_avx2_unaligned_erms+49>: ja 0x7ffff5eeb870 <__memset_avx2_erms>
17802 0x00007ffff5eeb870 <__memset_avx2_erms+0>: vzeroupper
17803 0x00007ffff5eeb873 <__memset_avx2_erms+3>: mov %rdx,%rcx
17804 0x00007ffff5eeb876 <__memset_avx2_erms+6>: movzbl %sil,%eax
17805 0x00007ffff5eeb87a <__memset_avx2_erms+10>: mov %rdi,%rdx
17806 0x00007ffff5eeb87d <__memset_avx2_erms+13>: rep stos %al,%es:(%rdi)
17807 0x00007ffff5eeb87f <__memset_avx2_erms+15>: mov %rdx,%rax
not sure what that means/why this causes a segfault?

I need some advice how to identify the source of the segfault.
The GDB stack trace is typical of stack overflow similar to:
int main()
{
char buf[1];
memset(buf, 0xbe, 1<<20);
}
It is surprising that AddressSanitizer didn't catch that overflow.
I would try to debug it with the GDB branch trace support, as described here.
P.S. If you can construct a minimal example, Address Sanitizer developers will be interested in it.

Is it being built and run on different machines/environments?
I observe such segfaults for the executable compiled with asan when it is built and run on different environments/machines (don't observe if the lib versions are same). i.e. without asan the app runs fine on different machine.
In my case, when I run an app with address sanitizer on different machine:
./dummy_logger
ASAN:SIGSEGV
=================================================================
==18213==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000 (pc 0xf7f45e60 bp 0x1ffff000 sp 0xffab0a4c T16777215)
#0 0xf7f45e5f in _dl_get_tls_static_info (/lib/ld-linux.so.2+0x11e5f)
#1 0xf7a59d1c (/usr/lib/i386-linux-gnu/libasan.so.2+0xacd1c)
#2 0xf7a4ddbd (/usr/lib/i386-linux-gnu/libasan.so.2+0xa0dbd)
#3 0xf7f438ea (/lib/ld-linux.so.2+0xf8ea)
#4 0xf7f34cb9 (/lib/ld-linux.so.2+0xcb9)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 _dl_get_tls_static_info
==18213==ABORTING
And works fine on the machine where it was compiled.

Related

Writing an efficient backtrace function

I came across below code for walking backtrace
struct stack_frame {
struct stack_frame *prev;
void *return_addr;
} __attribute__((packed));
typedef struct stack_frame stack_frame;
__attribute__((noinline, noclone))
void backtrace_from_fp(void **buf, int size)
{
int i;
stack_frame *fp;
__asm__("movl %%ebp, %[fp]" : /* output */ [fp] "=r" (fp));
for(i = 0; i < size && fp != NULL; fp = fp->prev, i++)
buf[i] = fp->return_addr;
}
the reason behind looking for this code is we are using a 3rd party malloc hook hence don't want to use backtrace which again allocates memory. Above doesn't work for x86_64 and I modified asm statement to
__asm__("movl %%rbp, %[fp]" : /* output */ [fp] "=r" (fp));
I get crash
(gdb) bt
#0 backtrace_from_fp (size=10, buf=<optimized out>) at src/tcmalloc.cc:1910
#1 tc_malloc (size=<optimized out>) at src/tcmalloc.cc:1920
#2 0x00007f5023ade58d in __fopen_internal () from /lib64/libc.so.6
#3 0x00007f501e687956 in selinuxfs_exists () from /lib64/libselinux.so.1
#4 0x00007f501e67fc28 in init_lib () from /lib64/libselinux.so.1
#5 0x00007f5029a32503 in _dl_init_internal () from /lib64/ld-linux-x86-64.so.2
#6 0x00007f5029a241aa in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#7 0x0000000000000001 in ?? ()
#8 0x00007fff22cb8e24 in ?? ()
#9 0x0000000000000000 in ?? ()
(gdb)
(gdb) p $rbp
$2 = (void *) 0x7f501e695f37
(gdb) p (stack_frame *)$rbp
$3 = (stack_frame *) 0x7f501e695f37
(gdb) p *$3
$4 = {prev = 0x69662f636f72702f, return_addr = 0x6d6574737973656c}
(gdb) x /1xw 0x69662f636f72702f
0x69662f636f72702f: Cannot access memory at address 0x69662f636f72702f
(gdb) fr
#0 backtrace_from_fp (size=10, buf=<optimized out>) at src/tcmalloc.cc:1910
1910 in src/tcmalloc.cc
(gdb)
Am I missing something ?. Any help on how can I reconstruct the same via code ?.
Am I missing something ?
The code you referenced assumes the compiled code is using frame pointer register chain.
This was the default on (32-bit) i*86 up until about 5-7 years ago, and has not been the default on x86_64 since ~forever.
The code will most likely work fine in non-optimized builds, but will fail miserably with optimization on both 32-bit and 64-bit x86 platforms using non-ancient versions of the compiler.
If you can rebuild all code (including libc) with -fno-omit-frame-pointer, then this code will work most of the time (but not all the time, because libc may have hand-coded assembly, and that assembly will not have frame pointer chain).
One solution is to use libunwind. Unfortunately, using it from inside malloc can still run into a problem, if you (or any libraries you use) also use dlopen.

sigsegv during __gcc_register_frame (mingw32)

I try to debug crash (sigsegv especially) of application that uses dynamic libraries (.dll). As I can see it crashes in statically linked part of code in library initialization. GDB shows something similar to (addresses are changing):
Program received signal SIGSEGV, Segmentation fault.
0x00e41290 in __gcc_register_frame ()
from library.dll
1: x/5i $pc
=> 0xe41290 <__gcc_register_frame+208>: movl $0xebc6f0,0x11f2000
0xe4129a <__gcc_register_frame+218>: mov $0xebc2b0,%esi
0xe4129f <__gcc_register_frame+223>: jmp 0xe41222 <__gcc_register_frame+98>
0xe412a1 <__gcc_register_frame+225>: jmp 0xe412b0 <__gcc_deregister_frame>
During the same session I can see that 0x11f2000 is correct part of library.dll
(gdb) info symbol 0x11f2000
deregister_frame_fn in section .data of library.dll
Mentioned address space is available from GDB, so setting/reading values is possible:
(gdb) print (unsigned char*)0x11f2000
$1 = (unsigned char *) 0x11f2000 <deregister_frame_fn> ""
(gdb) set *(unsigned char*)0x11f2000=1
(gdb) set *(unsigned char*)0x11f2001=2
(gdb) set *(unsigned char*)0x11f2002=3
(gdb) set *(unsigned char*)0x11f2003=4
(gdb) print (unsigned char*)0x11f2000
$2 = (unsigned char *) 0x11f2000 <deregister_frame_fn> "\001\002\003\004"
I wonder I'm not able to make short example in cpp, since another library we use in the same application (with the same compiler) is working fine.
The main question is why there may be crash like sigsegv if memory location is available in gdb?
gcc version 5.2.0 (Sourcery CodeBench)
Below backtrace:
(gdb) bt
#0 0x00e41290 in __gcc_register_frame ()
from library.dll
#1 0x00eb7afa in __do_global_ctors ()
from library.dll
#2 0x00e4110b in DllMainCRTStartup#12 ()
from library.dll
...

Why mingw+gdb cannot show backtrace correctly from inside a sigsegv handler?

I'm debugging a process that runs really slow when is executed from gdb on Windows (mingw32), so I decided to run it until it crash without gdb, and then to attach the debugger. I've installed a signal handler for sigsegv that shows its pid and waits, so when I see the message I load gdb and use the "attach" command with that pid. The problem is that gdb shows me an useless backtrace at that point. Here's an example:
void my_sigsegv_handler(int) {
std::cerr << "Segmentation fault! pid=" << GetCurrentProcessId();
std::cin.get(); // wait for gdb
}
int main() {
signal(SIGSEGV,my_sigsegv_handler);
int *p = 0;
std::cout << *p; // boom!
}
Compiled with "mingw32-g++ -g -O0", output from gdb's command "bt" (after selecting the proper thread) is:
#0 0x764e73ea in ?? ()
#1 0x7646f489 in ?? ()
#2 0x75edc3b3 in ?? ()
#3 0x75edc2bc in ?? ()
#4 0x75edc472 in ?? ()
#5 0x00415502 in __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char> >::uflow() ()
#6 0x00434f32 in std::istream::get() ()
#7 0x004016d5 in my_sigsegv_handler () at C:\Users\usuario\zinjai\sin_titulo.cpp:8
#8 0x004010f9 in _gnu_exception_handler (exception_data=0x28fa88) at ../mingwrt-4.0.3-1-mingw32-src/src/libcrt/crt/crt1.c:137
#9 0x76469d57 in ?? ()
#10 0x77100727 in ?? ()
#11 0x770c9d45 in ?? ()
#12 0x00000000 in ?? ()
Notice that this example does not corrupt stack when generating the segfault. Actualy, I can debug it anyway, just continuing execution. If I press enter the signal handler finishes, returns to the place where it was generated (main function), and the problem is not solved, but this time gdb is there to catch it. But I'd like to now how does it really works.
If I use the same method in gnu/linux I can see what I want to see here:
#5 0x00007f6809bf349e in std::istream::get() () from /usr/lib64/libstdc++.so.6
#6 0x00000000004008cd in my_signal_handler () at /home/zaskar/.zinjai/sin_titulo.cpp:6
#7 <signal handler called>
#8 0x00000000004008f9 in main (argc=1, argv=0x7fffa0613108) at /home/zaskar/.zinjai/sin_titulo.cpp:11
So the question is, why gdb cannot show me the correct backtrace from withing the signal handler? Or what am I doing wrong? Is there any better way to solve it?

Using Gdb debugger, how should I proceed to find out the cause of "Program terminated with signal 11, Segmentation fault."

Here is the backtrace of gdb,
Program terminated with signal 11, Segmentation fault.
#0 0xb7e78830 in Gtk::Widget::get_width () from /usr/lib/libgtkmm-2.4.so.1
(gdb) bt
#0 0xb7e78830 in Gtk::Widget::get_width () from /usr/lib/libgtkmm-2.4.so.1
#1 0x08221d5d in sigc::bound_mem_functor0<bool, videoScreen>::operator() (this=0xb1c04714)
at /usr/include/sigc++-2.0/sigc++/functors/mem_fun.h:1787`enter code here`
#2 0x08221d76 in sigc::adaptor_functor<sigc::bound_mem_functor0<bool, videoScreen> >::operator() (this=0xb1c04710)
at /usr/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h:251
#3 0x08221d96 in sigc::internal::slot_call0<sigc::bound_mem_functor0<bool, videoScreen>, bool>::call_it (rep=0xb1c046f8)
at /usr/include/sigc++-2.0/sigc++/functors/slot.h:103
#4 0xb7b1ed35 in ?? () from /usr/lib/libglibmm-2.4.so.1
#5 0xb73c6bb6 in ?? () from /usr/lib/libglib-2.0.so.0
#6 0xb28ff1f8 in ?? ()
#7 0xb647479c in __pthread_mutex_unlock_usercnt () from /lib/libpthread.so.0
#8 0xb73c6446 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#9 0xb73c97e2 in ?? () from /usr/lib/libglib-2.0.so.0
#10 0xb3d11af8 in ?? ()
#11 0x00000000 in ?? ()
I figured out the line of crash,here is the code around that line.
1:currPicLoaded = 1;
2:int status = -1;
3:zoomedPicWidth = drawVideo1->get_width();
I figured out that above line is 3 is the cause of crash, but this line execute 5 times before crash.So I do not know why it does crash at 6th time.
PS : Above line of code is with in a thread which run continuously.
Any help is more than welcome :)
how should I proceed
Your very first step should be to find out which instruction caused the SIGSEGV. Do this:
(gdb) x/i $pc
The most likely cause is that your drawVideo1 object is either dangling (has been deleted), or is corrupt in some other way.
Since you are apparently on Linux (you didn't say, but you should always say), the first tool to reach for for debugging "strange" problems like this is Valgrind.

DevIL segfault, issues with png's, bmp's

I am on mingw (gcc version 4.5.2).
I get a segfault when opening certain files, including PNGs and BMPs. It was working fine on a 128x128 PNG but when I started testing with larger files I started getting a segfault. There are no issues with the TGA format, though. I know the library works for the most part, but not knowing whether it will decide to crash and burn like this is not good.
gdb does not give me any hints about what's going on. I am able to compile DevIL from source, and I compiled a debug dll (--enable-debug for configure script) but it doesn't seem to support png (seems like I need to get a png12 library) but it doesn't get me very far.
I am trying to open a ~2MB BMP I made in GIMP. I run it through GDB and it sometimes will segfault but other times it warns of some stuff happening on the heap (lots of stuff i've never seen before). Here's a gdb run dump. All of the lines beginning with %%% are the output that is specific to my program, the rest comes from gdb.
$ gdb ./entropy_unittest_disp.exe loadpngdisplay
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp
\game/./entropy_unittest_disp.exe...done.
c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp\game/loadpngdisplay:
No such file or directory.
(gdb) r
Starting program: c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp\ga
me/./entropy_unittest_disp.exe
[New Thread 23284.0x5bb4]
%%%UNIT TEST BUILD: INTERNAL USE ONLY. DO NOT DISTRIBUTE
%%%Compiled on Sep 11 2011 at 09:45:38
%%%argc = 1: Main.cpp:119
%%%argv:
%%%0: c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp\game/./entropy_un
%%%ittest_disp.exe
%%%←[36mStarting Test ilWritePng, at Image.cpp:8←[0m
%%%rm: cannot lstat `output_il.png': No such file or directory
%%%ilGetError() = 1292: Image.cpp:25
%%%Completed Test ilWritePng in 0.033 seconds
%%%←[36mStarting Test loadPNGDisplay, at Image.cpp:31←[0m
[New Thread 23284.0x445c]
[New Thread 23284.0x1fd8]
[New Thread 23284.0x1424]
%%%Number of Joysticks detected: 2
%%%Opening Joystick: Harmonix Guitar for Xbox 360 (Controller)
[New Thread 23284.0x526c]
[New Thread 23284.0x5a70]
[New Thread 23284.0x1ae8]
[New Thread 23284.0x5908]
[New Thread 23284.0x5974]
%%%Using GLEW 1.5.8
%%%OpenGL Vendor: NVIDIA Corporation
%%%OpenGL Renderer: GeForce GTX 260/PCI/SSE2
%%%OpenGL Version: 3.3.0
warning: HEAP[entropy_unittest_disp.exe]:
warning: Invalid address specified to RtlFreeHeap( 00350000, 04000000 )
Program received signal SIGTRAP, Trace/breakpoint trap.
0x772e0475 in ntdll!TpWaitForAlpcCompletion ()
from C:\Windows\system32\ntdll.dll
(gdb) where
#0 0x772e0475 in ntdll!TpWaitForAlpcCompletion ()
from C:\Windows\system32\ntdll.dll
#1 0x0028f510 in ?? ()
#2 0x772a29c0 in ntdll!RtlCopyExtendedContext ()
from C:\Windows\system32\ntdll.dll
#3 0x03fffff8 in ?? ()
#4 0x772e14cf in ntdll!TpQueryPoolStackInformation ()
from C:\Windows\system32\ntdll.dll
#5 0x00350000 in ?? ()
#6 0x7729ab3a in ntdll!AlpcMaxAllowedMessageLength ()
from C:\Windows\system32\ntdll.dll
#7 0x00350000 in ?? ()
#8 0x77243472 in ntdll!RtlLargeIntegerShiftRight ()
from C:\Windows\system32\ntdll.dll
#9 0x03fffff8 in ?? ()
#10 0x766398cd in msvcrt!free () from C:\Windows\syswow64\msvcrt.dll
#11 0x00350000 in ?? ()
#12 0x6180129c in _mm_free (aligned_ptr=0x8230020)
at c:/mingw/bin/../lib/gcc/mingw32/4.5.2/include/mm_malloc.h:71
#13 0x61801370 in DefaultFreeFunc (ptr=0x8230020)
at ./../src-IL/src/il_alloc.c:127
#14 0x618012ee in ifree (Ptr=0x8230020) at ./../src-IL/src/il_alloc.c:99
#15 0x618149f8 in iPreCache (Size=592128) at ./../src-IL/src/il_files.c:550
#16 0x618148a2 in iReadFile (Buffer=0x8100017, Size=1, Number=2313)
at ./../src-IL/src/il_files.c:499
#17 0x61808cf5 in ilReadUncompBmp (Header=0x28f829)
at ./../src-IL/src/il_bmp.c:486
#18 0x61808410 in iLoadBitmapInternal () at ./../src-IL/src/il_bmp.c:250
#19 0x618082f3 in ilLoadBmpF (File=0x766d2960) at ./../src-IL/src/il_bmp.c:199
#20 0x618082ba in ilLoadBmp (FileName=0x4c25f1 "folder.bmp")
at ./../src-IL/src/il_bmp.c:184
#21 0x61830bf0 in ilLoadImage (FileName=0x4c25f1 "folder.bmp")
at ./../src-IL/src/il_io.c:1827
#22 0x0040f66c in SDLSystemloadPNGDisplayHelper::RunImpl (this=0x28fc10)
at Image.cpp:40
#23 0x00461e74 in UnitTest::ExecuteTest<SDLSystemloadPNGDisplayHelper> (
testObject=..., details=...) at ../include/UnitTest++/ExecuteTest.h:25
#24 0x0040f2cd in TestSDLSystemloadPNGDisplay::RunImpl (this=0x4e5cf8)
at Image.cpp:31
#25 0x00463023 in UnitTest::ExecuteTest<UnitTest::Test> (testObject=...,
details=...) at src/ExecuteTest.h:25
#26 0x0044198d in UnitTest::Test::Run (this=0x4e5cf8) at src/Test.cpp:34
#27 0x00441d9a in UnitTest::TestRunner::RunTest (this=0x28fedc,
result=0x3517f0, curTest=0x4e5cf8, maxTestTimeInMs=0)
at src/TestRunner.cpp:61
#28 0x00466b7e in UnitTest::TestRunner::RunTestsIf<UnitTest::True> (
this=0x28fedc, list=..., suiteName=0x0, predicate=..., maxTestTimeInMs=0)
at ../include/UnitTest++/TestRunner.h:40
#29 0x004014e3 in UnitTest::RunAllTestsVerbose () at Main.cpp:72
#30 0x0040167d in main (argc=1, argv=0x3531d8) at Main.cpp:126
(gdb) c
Continuing.
warning: HEAP[entropy_unittest_disp.exe]:
warning: Invalid address specified to RtlFreeHeap( 00350000, 04000000 )
Program received signal SIGTRAP, Trace/breakpoint trap.
0x772e0475 in ntdll!TpWaitForAlpcCompletion ()
from C:\Windows\system32\ntdll.dll
(gdb) c
Continuing.
warning: HEAP[entropy_unittest_disp.exe]:
warning: Invalid address specified to RtlFreeHeap( 00350000, 04000000 )
Program received signal SIGTRAP, Trace/breakpoint trap.
0x772e0475 in ntdll!TpWaitForAlpcCompletion ()
from C:\Windows\system32\ntdll.dll
(gdb)
Continuing.
warning: HEAP[entropy_unittest_disp.exe]:
warning: Invalid address specified to RtlFreeHeap( 00350000, 04000000 )
Program received signal SIGTRAP, Trace/breakpoint trap.
0x772e0475 in ntdll!TpWaitForAlpcCompletion ()
from C:\Windows\system32\ntdll.dll
(gdb)
Continuing.
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 23284.0x5974]
0x05064225 in nvoglv32!DrvGetProcAddress ()
from C:\Windows\SysWOW64\nvoglv32.dll
(gdb)
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x05064225 in nvoglv32!DrvGetProcAddress ()
from C:\Windows\SysWOW64\nvoglv32.dll
(gdb)
Continuing.
Program exited with code 030000000005.
(gdb)
The program is not being run.
(gdb) r
Starting program: c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp\ga
me/./entropy_unittest_disp.exe
[New Thread 23428.0x49b8]
%%%UNIT TEST BUILD: INTERNAL USE ONLY. DO NOT DISTRIBUTE
%%%Compiled on Sep 11 2011 at 09:45:38
%%%argc = 1: Main.cpp:119
%%%argv:
%%%0: c:\Users\Steven\Dropbox\Programming\entropy_p5_makefile\cpp\game/./entropy_un
%%%ittest_disp.exe
%%%←[36mStarting Test ilWritePng, at Image.cpp:8←[0m
Program received signal SIGSEGV, Segmentation fault.
0x7723dfc4 in ntdll!LdrWx86FormatVirtualImage ()
from C:\Windows\system32\ntdll.dll
(gdb) where
#0 0x7723dfc4 in ntdll!LdrWx86FormatVirtualImage ()
from C:\Windows\system32\ntdll.dll
#1 0x1f002150 in ?? ()
#2 0x00000000 in ?? ()
(gdb)
the test ilWritePng is actually just having it write a .tga image file. That test works fine with the release dll (md5 = 59E291838AE2C88F5F71108E4845A84B) but this debug build I compiled has more issues.
I was so happy when I skimmed the doc and got DevIL up and running in like 10 minutes. I figured it was going to save me so much work...
This is making me start to wonder if I should just implement my own image file format (I would use PPM binary and shove it through a compression stream).
edit: source code:
#include "Texture.h" // for Pixel struct
#include "Script.h" // for lua (quick and dirty shell access)
TEST_FIXTURE(ILSystem, ilWritePng) { // ILSystem calls ilInit(), ilShutDown() in ctor, dtor respectively
ILuint image;
ilGenImages(1,&image);
CHECK(ilGetError()==0);
ilBindImage(image);
Pixel pixels[128*128];
for (int i=0;i<128;++i) { for (int j=0;j<128;++j) {
Pixel &p = pixels[i*128+j];
p.b = 0; p.g = i; p.r = j; p.a = 0xff;
}} // neat and simple test image, a greenish purplish gradient type thing.
CHECK(ilTexImage(128,128,1,4,IL_BGRA, IL_UNSIGNED_BYTE,pixels));
CHECK(ilGetError()==0);
{
LuaSystem l;
l.dostring("os.execute(\"rm output_il.tga\")"); // delete that file
}
ilSaveImage("output_il.tga");
PRINT_INT(ilGetError());
}
#ifdef LOAD_DISPLAY
#include "SDLOGL.h"
#include "Texture.h"
TEST_FIXTURE(SDLSystem, loadPNGDisplay) { // takes care of initing SDL and opengl context
ILSystem s; // RAII = peace of mind
// i can't use two fixtures in one unittest. but this does the same thing anyway.
ILuint image;
CHECK(ilGetError()==0);
ilGenImages(1,&image);
CHECK(ilGetError()==0);
ilBindImage(image);
CHECK(ilGetError()==0);
ilLoadImage("folder.bmp");
CHECK(ilGetError()==0);
ILubyte *pixelData = ilGetData(); CHECK(pixelData);
CHECK(ilGetError()==0);
GLuint tex = loadImage32(pixelData,ilGetInteger(IL_IMAGE_WIDTH),ilGetInteger(IL_IMAGE_HEIGHT),0);
// i do not know exactly how its encoded. but it seems like when loading pngs it is in RGBA format
PRINT_INT(ilGetInteger(IL_FORMAT_MODE));
CHECK(ilGetError()==0);
initOrthoRender();
drawTexture(tex);
CHECK(glGetError()==0);
SDL_GL_SwapBuffers();
SLEEP(500);
}
#endif //LOAD_DISPLAY