RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior)

Pierre Muller
2012-12-09T12:45:57Z

Hi Yuanhui,

> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de asmwarrior
> Envoyé : dimanche 9 décembre 2012 03:48
> À : Pierre Muller
> Cc : 'Joel Brobecker'; 'Eli Zaretskii'; gdb-patches@sourceware.org
> Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling
> __stdcall functions in the inferior)
>
> On 2012-12-9 2:00, Pierre Muller wrote:
> > This memory corruption is rather odd...
> > it seems that the rva_end of index=2 seems to contains the same data
> > as the section_name for index 4...
> > This array is really created only inside read_pe_exported_syms
> > so that it would be worth trying to add a breakpoint at that function,
> > and step over it for ntdll.dll to understand when the data gets
> corrupted...
> >
> > Would it be possible for you to upload the codeblocks executable that
> triggers
> > the problem somewhere so I could
> > check if I get the same errors and debug further?
> >
> > I have no idea what is going on...
> >
> >
> > Pierre Muller
> >
> Hi, Pierre:
>
> I think you can test the official Codeblocks release 12.11.
>
> 1, you can download the release from: http://www.codeblocks.org/downloads/26
> select this one: codeblocks-12.11-setup.exe
> Note: the binaries in this release contain debug information (build with -g
> options)

Strange because I did install program that you are refereeing to above,
but the installed codeblock.exe files doesn't contain any debug information,
see elow:

C:\Program Files (x86)\CodeBlocks\debug>dir codeblocks.exe
Le volume dans le lecteur C s'appelle OS
Le numéro de série du volume est 4801-E7AF

Répertoire de C:\Program Files (x86)\CodeBlocks\debug

28/11/2012 20:08 1 253 390 codeblocks.exe
1 fichier(s) 1 253 390 octets
0 Rép(s) 2 344 669 184 octets libres

C:\Program Files (x86)\CodeBlocks\debug>gdbcvs codeblocks.exe
GNU gdb (GDB) 7.5.50.20121106-cvs
Copyright (C) 2012 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 "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\Program Files (x86)\CodeBlocks\debug\codeblocks.exe...(no debugging symbols found)...done.
(gdb) q

C:\Program Files (x86)\CodeBlocks\debug>objdump -h codeblocks.exe

codeblocks.exe: file format pei-i386

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000b550c 00401000 00401000 00000400 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00000100 004b7000 004b7000 000b5a00 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .rdata 0001bb30 004b8000 004b8000 000b5c00 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .eh_frame 00000438 004d4000 004d4000 000d1800 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .bss 000086dc 004d5000 004d5000 00000000 2**5
ALLOC
5 .edata 00000985 004de000 004de000 000d1e00 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .idata 00014120 004df000 004df000 000d2800 2**2
CONTENTS, ALLOC, LOAD, DATA
7 .CRT 00000018 004f4000 004f4000 000e6a00 2**2
CONTENTS, ALLOC, LOAD, DATA
8 .tls 00000020 004f5000 004f5000 000e6c00 2**2
CONTENTS, ALLOC, LOAD, DATA
9 .rsrc 0003bc0c 004f6000 004f6000 000e6e00 2**2
CONTENTS, ALLOC, LOAD, DATA
10 .reloc 0000f2c8 00532000 00532000 00122c00 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA

C:\Program Files (x86)\CodeBlocks\debug>

Are you sure it's the file from codeblocks-12.11-setup.exe
that you are analyzing?

> 2, install it on your system
>
> 3, did the following steps:
>
> E:\code\gcc\PCXMinGW463\bin>gdb_stable.exe GDB
> GNU gdb (GDB) 7.5.50.20121126-cvs
> Copyright (C) 2012 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 E:\code\gcc\PCXMinGW463\bin\GDB.exe...done.
> (gdb) r
> Starting program: E:\code\gcc\PCXMinGW463\bin\GDB.exe
> [New Thread 2816.0xb98]
> GNU gdb (GDB) 7.5.50.20121207-cvs
> Copyright (C) 2012 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/>.
> (gdb) [New Thread 2816.0xe50]
> [New Thread 2816.0x484]
> file d:/software/cb/codeblocks/codeblocks.exe
> Reading symbols from d:\software\cb\codeblocks\codeblocks.exe...warning:
> HEAP[GD
> B.exe]:
> warning: HEAP: Free Heap block 2de4228 modified at 2de424c after it was
> freed

STOP right here!

You get a warning about memory corruption before the crash!
So you need to find out why you get this.

The best would be to start GDB from gdb_stable using
start command and place an access watchpoint on the location
that is given (if the address is the same for different runs...)
awatch *0x2de4228
should allow to get more information.
It might not work right after start command,
because the corresponding memory block might
not yet be accessible by the program,
in that case try to add a breakpoint
at read_pe_exported_syms function,
and try to insert the watchpoint at each stop at that breakpoint.

This way, we might finally understand which allocated memory
is accessed after being freed.

> Program received signal SIGTRAP, Trace/breakpoint trap.
> 0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
> (gdb) bt
> #0 0x7c90120f in ntdll!DbgUiConnectToDbg ()
> from C:\WINDOWS\system32\ntdll.dll
> #1 0x7c96ee31 in ntdll!RtlpNtMakeTemporaryKey ()
> from C:\WINDOWS\system32\ntdll.dll
> #2 0x7c94b302 in ntdll!LdrFindEntryForAddress ()
> from C:\WINDOWS\system32\ntdll.dll
> #3 0x02de4228 in ?? ()
> #4 0x7c96fb98 in ntdll!RtlpNtMakeTemporaryKey ()
> from C:\WINDOWS\system32\ntdll.dll
> #5 0x7c94b244 in ntdll!LdrFindEntryForAddress ()
> from C:\WINDOWS\system32\ntdll.dll
> #6 0x002e0000 in ?? ()
> #7 0x7c919c0c in ntdll!RtlpUnWaitCriticalSection ()
> from C:\WINDOWS\system32\ntdll.dll
> #8 0x77c2c3c9 in msvcrt!free () from C:\WINDOWS\system32\msvcrt.dll
> #9 0x002e0000 in ?? ()
> #10 0x77c2c3e7 in msvcrt!free () from C:\WINDOWS\system32\msvcrt.dll

Is it "normal" that msvcrt call to malloc can call free?

> #11 0x00000010 in ?? ()
> #12 0x0285f568 in ?? ()
> #13 0x77c2c42e in msvcrt!malloc () from C:\WINDOWS\system32\msvcrt.dll
> #14 0x006284a2 in xmalloc (size=16) at ../../gdb/gdb/common/common-
> utils.c:50
> #15 0x004baa3e in make_my_cleanup2 (pmy_chain=0x7508e0 <cleanup_chain>,
> function=0x628579 <xfree>, arg=0x2ddb7d8, free_arg=0x0)
> at ../../gdb/gdb/cleanups.c:82
> #16 0x004baad4 in make_my_cleanup (pmy_chain=0x7508e0 <cleanup_chain>,
> function=0x628579 <xfree>, arg=0x2ddb7d8) at
> ../../gdb/gdb/cleanups.c:108
> #17 0x004baaf6 in make_cleanup (function=0x628579 <xfree>, arg=0x2ddb7d8)
> at ../../gdb/gdb/cleanups.c:119
> #18 0x00563ae3 in read_pe_exported_syms (objfile=0x2ddc9c0)
> at ../../gdb/gdb/coff-pe-read.c:490
> #19 0x00560887 in coff_symtab_read (symtab_offset=1253376, nsyms=0,
> objfile=0x2ddc9c0) at ../../gdb/gdb/coffread.c:1127
> #20 0x0055f660 in coff_symfile_read (objfile=0x2ddc9c0, symfile_flags=6)
> at ../../gdb/gdb/coffread.c:610
> #21 0x004f1cc4 in read_symbols (objfile=0x2ddc9c0, add_flags=6)
> at ../../gdb/gdb/symfile.c:885
> #22 0x004f203b in syms_from_objfile (objfile=0x2ddc9c0, addrs=0x2de2bc0,
> offsets=0x0, num_offsets=0, add_flags=6) at
> ../../gdb/gdb/symfile.c:1020
> #23 0x004f2206 in symbol_file_add_with_addrs_or_offsets (abfd=0x2dd8508,
> add_flags=6, addrs=0x0, offsets=0x0, num_offsets=0, flags=8,
> parent=0x0)
> at ../../gdb/gdb/symfile.c:1123
> #24 0x004f23bf in symbol_file_add_from_bfd (abfd=0x2dd8508, add_flags=6,
> addrs=0x0, flags=8, parent=0x0) at ../../gdb/gdb/symfile.c:1213
> #25 0x004f240b in symbol_file_add (
> name=0x2dd8388 "d:/software/cb/codeblocks/codeblocks.exe", add_flags=6,
> addrs=0x0, flags=8) at ../../gdb/gdb/symfile.c:1229
> #26 0x004f248b in symbol_file_add_main_1 (
> args=0x2dd8388 "d:/software/cb/codeblocks/codeblocks.exe", from_tty=1,
> flags=8) at ../../gdb/gdb/symfile.c:1255
> #27 0x004f2ebc in symbol_file_command (
> args=0x2e4325 "d:/software/cb/codeblocks/codeblocks.exe", from_tty=1)
> at ../../gdb/gdb/symfile.c:1661
> #28 0x0054f045 in file_command (
> arg=0x2e4325 "d:/software/cb/codeblocks/codeblocks.exe", from_tty=1)
> at ../../gdb/gdb/exec.c:357
> #29 0x00447794 in do_cfunc (c=0x2daf7a0,
> args=0x2e4325 "d:/software/cb/codeblocks/codeblocks.exe", from_tty=1)
> at ../../gdb/gdb/cli/cli-decode.c:114
> #30 0x0044a0ce in cmd_func (cmd=0x2daf7a0,
> args=0x2e4325 "d:/software/cb/codeblocks/codeblocks.exe", from_tty=1)
> at ../../gdb/gdb/cli/cli-decode.c:1859
> #31 0x005f6ebf in execute_command (p=0x2e434c "e", from_tty=1)
> at ../../gdb/gdb/top.c:491
> #32 0x00524cda in command_handler (command=0x2e4320 "")
> at ../../gdb/gdb/event-top.c:429
> #33 0x0052524e in command_line_handler (
> rl=0x2dd8150 "file d:/software/cb/codeblocks/codeblocks.exe")
> at ../../gdb/gdb/event-top.c:630
> #34 0x00630133 in rl_callback_read_char ()
> at ../../gdb/readline/callback.c:220
> #35 0x0052481f in rl_callback_read_char_wrapper (client_data=0x0)
> at ../../gdb/gdb/event-top.c:163
> #36 0x00524c04 in stdin_event_handler (error=0, client_data=0x0)
> at ../../gdb/gdb/event-top.c:369
> #37 0x00523df9 in handle_file_event (data=...)
> at ../../gdb/gdb/event-loop.c:827
> #38 0x0052353d in process_event () at ../../gdb/gdb/event-loop.c:401
> #39 0x00523602 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465
> #40 0x00523654 in start_event_loop () at ../../gdb/gdb/event-loop.c:490
> #41 0x00524848 in cli_command_loop () at ../../gdb/gdb/event-top.c:176
> #42 0x0051cdcf in current_interp_command_loop ()
> at ../../gdb/gdb/interps.c:332
> #43 0x0051d6e9 in captured_command_loop (data=0x0) at
> ../../gdb/gdb/main.c:256
> #44 0x0051be8c in catch_errors (func=0x51d6d4 <captured_command_loop>,
> func_args=0x0, errstring=0x7af593 <__PRETTY_FUNCTION__.13689+121> "",
> mask=6) at ../../gdb/gdb/exceptions.c:546
> #45 0x0051e8c7 in captured_main (data=0x285fee0) at
> ../../gdb/gdb/main.c:1032
> #46 0x0051be8c in catch_errors (func=0x51d923 <captured_main>,
> func_args=0x285fee0,
> errstring=0x7af593 <__PRETTY_FUNCTION__.13689+121> "", mask=6)
> at ../../gdb/gdb/exceptions.c:546
> #47 0x0051e8fd in gdb_main (args=0x285fee0) at ../../gdb/gdb/main.c:1041
> #48 0x00401737 in main (argc=1, argv=0x2e3ea0) at ../../gdb/gdb/gdb.c:34
> (gdb) frame 18
> #18 0x00563ae3 in read_pe_exported_syms (objfile=0x2ddc9c0)
> at ../../gdb/gdb/coff-pe-read.c:490
> 490 make_cleanup (xfree, name);
> (gdb) p dll
> $1 = (bfd *) 0x2dd8508
> (gdb) p *dll
> $2 = {id = 0,
> filename = 0x2dba880 "d:\\software\\cb\\codeblocks\\codeblocks.exe",
> xvec = 0x84a380 <i386pei_vec>, iostream = 0x77c5fd60 <msvcrt!_iob+224>,
> iovec = 0x837480 <cache_iovec>, lru_prev = 0x2dd8508, lru_next =
> 0x2dd8508,
> where = 464, mtime = 1354129698, ifd = 0, format = bfd_object,
> direction = read_direction, flags = 65795, origin = 0, proxy_origin = 0,
> section_htab = {table = 0x2dd8630,
> newfunc = 0x64def8 <bfd_section_hash_newfunc>, memory = 0x2dd8600,
> size = 251, count = 11, entsize = 184, frozen = 0}, sections =
> 0x2dd8a30,
> section_last = 0x2dd9160, section_count = 11, start_address = 4199072,
> symcount = 0, outsymbols = 0x0, dynsymcount = 0,
> arch_info = 0x837700 <bfd_i386_arch>, arelt_data = 0x0, my_archive = 0x0,
> archive_next = 0x0, archive_head = 0x0, nested_archives = 0x0,
> link_next = 0x0, archive_pass = 0, tdata = {aout_data = 0x2dba8d0,
> aout_ar_data = 0x2dba8d0, oasys_obj_data = 0x2dba8d0,
> oasys_ar_data = 0x2dba8d0, coff_obj_data = 0x2dba8d0,
> pe_obj_data = 0x2dba8d0, xcoff_obj_data = 0x2dba8d0,
> ecoff_obj_data = 0x2dba8d0, ieee_data = 0x2dba8d0,
> ieee_ar_data = 0x2dba8d0, srec_data = 0x2dba8d0,
> verilog_data = 0x2dba8d0, ihex_data = 0x2dba8d0, tekhex_data =
> 0x2dba8d0,
> elf_obj_data = 0x2dba8d0, nlm_obj_data = 0x2dba8d0,
> bout_data = 0x2dba8d0, mmo_data = 0x2dba8d0, sun_core_data = 0x2dba8d0,
> sco5_core_data = 0x2dba8d0, trad_core_data = 0x2dba8d0,
> som_data = 0x2dba8d0, hpux_core_data = 0x2dba8d0,
> hppabsd_core_data = 0x2dba8d0, sgi_core_data = 0x2dba8d0,
> lynx_core_data = 0x2dba8d0, osf_core_data = 0x2dba8d0,
> cisco_core_data = 0x2dba8d0, versados_data = 0x2dba8d0,
> netbsd_core_data = 0x2dba8d0, mach_o_data = 0x2dba8d0,
> mach_o_fat_data = 0x2dba8d0, plugin_data = 0x2dba8d0,
> pef_data = 0x2dba8d0, pef_xlib_data = 0x2dba8d0, sym_data = 0x2dba8d0,
> any = 0x2dba8d0}, usrdata = 0x2dba8b0, memory = 0x2dd85d8, cacheable =
> 1,
> target_defaulted = 1, opened_once = 1, mtime_set = 0, no_export = 0,
> output_has_begun = 0, has_armap = 0, is_thin_archive = 0,
> selective_search = 0}
> (gdb)
>
> Here, it looks like this crash come from the gdb(debugee) reading pe symbols
> in codeblocks.exe
> it crash here (When I run the file command):
>
> #18 0x00563ae3 in read_pe_exported_syms (objfile=0x2ddc9c0)
> at ../../gdb/gdb/coff-pe-read.c:490
>
> else
> {
> char *name;
>
> section_data = xrealloc (section_data, otherix+1
> * sizeof (struct read_pe_section_data));
> name = xstrdup (sec_name);
> section_data[otherix].section_name = name;
> make_cleanup (xfree, name);//******************crash here
> section_data[otherix].rva_start = vaddr;
> section_data[otherix].rva_end = vaddr + vsize;
> section_data[otherix].vma_offset = 0;
> if (characteristics & IMAGE_SCN_CNT_CODE)
> section_data[otherix].ms_type = mst_text;
> else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
> section_data[otherix].ms_type = mst_data;
> else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
> section_data[otherix].ms_type = mst_bss;
> else
> section_data[otherix].ms_type = mst_unknown;
> otherix++;
> }
> }
>
> So, I think you can test this C::B release.

The make_cleanup call generates a malloc call to an already corrupted heap,
so that it probably only exposes the problem, but it is not necessarily the
cause of the problem.

> Yuanhui Zhang

Thanks again for you time,

Pierre