* [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <83y5jb7rfe.fsf@gnu.org> @ 2012-10-15 13:36 ` Pierre Muller 2012-10-24 19:45 ` Joel Brobecker [not found] ` <006001cdaada$00c81f00$02585d00$%muller@ics-cnrs.unistra.fr> 1 sibling, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-10-15 13:36 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 2815 bytes --] Eli reported a problem with GDB trying to call a function in kernel32.dll. The idea that the calling convention was responsible for the signal when trying to call a function declared in kernel32 dll did not make muich sense for a function like GetLastError, which has no parameters. All i386 calling convention agree that simple return values should be in register EAX. Anyhow an error on location of return value should only have the effect of losing the correct return value but never generate a signal... After some investigation, I noticed that the minimal symbol GetLastError was offset by 0xf0000 respective to the '_imp__GetLastError@0'. The patch attached allowed me to call (gdb) call GetLastError () And get a simple $2 = 126 (for instance, depending on when you do the call). Could someone please test the patch and confirm that it does fix the problem? The main fix consists in a new function pe_text_section_offset that I added to coff-pe-read.c source, which allows to fetch the real offset of the .text section relative to the image base, instead of assuming 0x1000. I tried to leave the code in windows_xfer_shared_library "backward compatible", in the sense that if the DLL is not available (as might happen using gdbserver) we still default to 0x1000 value. In fact, the patch contains a second fix about the parsing of exported symbols, which currently can mix symbol names and associated RVA addresses if some function had a imposed ordinal value (which can lead to empty entries in the RVA addresses array). I did not separate the two parts as I was unsure if they are really independent. Comments most welcome, Pierre Muller GDB pascal language maintainer > -----Message d'origine----- > De : gdb-owner@sourceware.org [mailto:gdb-owner@sourceware.org] De la part > de Eli Zaretskii > Envoyé : vendredi 12 octobre 2012 15:26 > À : Pedro Alves > Cc : mark.kettenis@xs4all.nl; gdb@sourceware.org > Objet : Re: Calling __stdcall functions in the inferior > > > Date: Fri, 12 Oct 2012 12:27:53 +0100 > > From: Pedro Alves <palves@redhat.com> > > CC: Mark Kettenis <mark.kettenis@xs4all.nl>, gdb@sourceware.org > > > > In gcc/config/i386/winnt.c: > > > > /* Return string which is the function name, identified by ID, modified > > with a suffix consisting of an atsign (@) followed by the number of > > bytes of arguments. If ID is NULL use the DECL_NAME as base. If > > FASTCALL is true, also add the FASTCALL_PREFIX. > > Return NULL if no change required. */ > > > > static tree > > gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall) > > { > > > > As you see above, fastcall also has identifiable decoration. > > Thanks. [-- Attachment #2: fix-dll-offset.patch --] [-- Type: application/octet-stream, Size: 7399 bytes --] projecttype:gdb revision:HEAD email:muller@ics.u-strasbg.fr 2012-10-15 Pierre Muller <muller@ics.u-strasbg.fr> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (pe_as16): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function. (pe_text_section_offset): New function. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: src/gdb/coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- src/gdb/coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ src/gdb/coff-pe-read.h 15 Oct 2012 12:36:49 -0000 @@ -21,11 +21,15 @@ #if !defined (COFF_PE_READ_H) #define COFF_PE_READ_H +#include "defs.h" struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: src/gdb/coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.17 diff -u -p -r1.17 coff-pe-read.c --- src/gdb/coff-pe-read.c 4 Jan 2012 08:17:00 -0000 1.17 +++ src/gdb/coff-pe-read.c 15 Oct 2012 12:36:49 -0000 @@ -170,6 +170,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -336,26 +344,119 @@ read_pe_exported_syms (struct objfile *o { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, func_rva, section_data + sectix, dll_name, objfile); break; } } + if (!section_found) + { + char * forward_name = (char *) (erva + func_rva); + char * funcname = (char *) (erva + name_rva); + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + printf ("%s is a forward to %s\n", funcname, forward_name); + } } /* Discard expdata. */ do_cleanups (back_to); } + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + bfd *dll = abfd; + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + + char const *target = bfd_get_target (dll); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return 0; + } + + /* Get pe_header, optional header and numbers of export entries. */ + pe_header_offset = pe_get32 (dll, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + if (is_pe64) + num_entries = pe_get32 (dll, opthdr_ofs + 108); + else + num_entries = pe_get32 (dll, opthdr_ofs + 92); + + if (num_entries < 1) /* No exports. */ + { + return 0; + } + + if (is_pe64) + { + export_rva = pe_get32 (dll, opthdr_ofs + 112); + export_size = pe_get32 (dll, opthdr_ofs + 116); + } + else + { + export_rva = pe_get32 (dll, opthdr_ofs + 96); + export_size = pe_get32 (dll, opthdr_ofs + 100); + } + nsections = pe_get16 (dll, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (dll, pe_header_offset + 4 + 16)); + expptr = 0; + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long vsize = pe_get32 (dll, secptr1 + 16); + unsigned long fptr = pe_get32 (dll, secptr1 + 20); + + bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, dll); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return 0; +} Index: src/gdb/windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 windows-tdep.c --- src/gdb/windows-tdep.c 5 Jun 2012 13:50:57 -0000 1.16 +++ src/gdb/windows-tdep.c 15 Oct 2012 12:36:49 -0000 @@ -27,6 +27,9 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,6 +390,9 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + CORE_ADDR default_text_offset = 0x1000; obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); @@ -395,7 +401,19 @@ windows_xfer_shared_library (const char* /* The symbols in a dll are offset by 0x1000, which is the offset from 0 of the first byte in an image - because of the file header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + if (dll != NULL) + { + text_offset = pe_text_section_offset (dll); + if (text_offset != default_text_offset) + warning (_("DLL %s has .text section at offset %s\n"),so_name, + core_addr_to_string (text_offset)); + gdb_bfd_unref (dll); + } + else + text_offset = default_text_offset; + + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-10-15 13:36 ` [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) Pierre Muller @ 2012-10-24 19:45 ` Joel Brobecker 2012-10-25 12:21 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Joel Brobecker @ 2012-10-24 19:45 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches Hi Pierre, I don't know COFF/PE all that well, so I'll just trust you on the extraction of the information itself. Thanks for taking this on, by the way. Oh dear - I just realized midway through the review that the patch appears to be checked in already. I must have missed the associated emails.... I've continued the review anyways - it's nothing major, but there are a few nits I noticed. If you don't have time to look at them, no problem; I'll try to get to them. But do let me know. > 2012-10-15 Pierre Muller <muller@ics.u-strasbg.fr> > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > * coff-pe-read.c (pe_as16): New function. > (read_pe_exported_syms): Use ordinal of function to > retrieve correct RVA address of function. > (pe_text_section_offset): New function. > > * windows-tdep.c (windows_xfer_shared_library): Use > pe_text_section_offset function instead of possibly wrong > 0x1000 constant for .text sextion offset. > @@ -336,26 +344,119 @@ read_pe_exported_syms (struct objfile *o > { > /* Pointer to the names vector. */ > unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); > + /* Retrieve ordinal value */ > + > + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); Just a nit: Can we keep the formatting consistent between the two local variables? In other words, no empty line between the comment and the variable? > + if (!section_found) > + { > + char * forward_name = (char *) (erva + func_rva); > + char * funcname = (char *) (erva + name_rva); > + if ((func_rva >= export_rva) > + && (func_rva < export_rva + export_size)) Can you add an empty line between the variable declarations and the rest of the code. Also, the if condition is idented using spaces instead of tabs... > + printf ("%s is a forward to %s\n", funcname, forward_name); I don't think a printf is appropriate, here. Is that meant to be a warning? > +CORE_ADDR > +pe_text_section_offset (struct bfd *abfd) Can you add a description of what the function does? > + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; This is a nit as well, but can you rename opthdr_ofs? I'm a little confused, as the 's' at the end made me think that it was a plural, and thus that it was a set of offsets. But looking at the type and at the code, I am thinking now that this is a short for "offset", except an 'f' would be missing. How about spelling offset entirely? > + unsigned char *expdata, *erva; Should we be using gdb_byte *, in this case? I'm wondering if we should be adjusting the pe_get* & pe_as* routines as well... > + if (!is_pe32 && !is_pe64) > + { > + /* This is not a recognized PE format file. Abort now, because > + the code is untested on anything else. *FIXME* test on > + further architectures and loosen or remove this test. */ > + return 0; > + } I think a complaint would be appropriate, here. And I'm wondering if there might be a better way to check which PE format it is other than looking at a string... > + if (num_entries < 1) /* No exports. */ > + { > + return 0; > + } Formatting: Can you remove the curly braces? For one statement, our codig style says that we should not be using them. > @@ -387,6 +390,9 @@ windows_xfer_shared_library (const char* > struct gdbarch *gdbarch, struct obstack *obstack) > { > char *p; > + struct bfd * dll; > + CORE_ADDR text_offset; > + CORE_ADDR default_text_offset = 0x1000; > obstack_grow_str (obstack, "<library name=\""); Can you add an empty line after the local variable declarations? > + if (text_offset != default_text_offset) > + warning (_("DLL %s has .text section at offset %s\n"),so_name, Missing space after the coma (just before 'so_name'). -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-10-24 19:45 ` Joel Brobecker @ 2012-10-25 12:21 ` Pierre Muller 2012-11-05 17:11 ` Joel Brobecker 0 siblings, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-10-25 12:21 UTC (permalink / raw) To: 'Joel Brobecker'; +Cc: gdb-patches Hi Joel, > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Joel Brobecker > Envoyé : mercredi 24 octobre 2012 21:45 > À : Pierre Muller > Cc : gdb-patches@sourceware.org > Objet : Re: [RFC] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > Hi Pierre, > > I don't know COFF/PE all that well, so I'll just trust you on > the extraction of the information itself. Thanks for taking this on, > by the way. Thanks for the review. > Oh dear - I just realized midway through the review that the patch > appears to be checked in already. I must have missed the associated > emails.... I've continued the review anyways - it's nothing major, > but there are a few nits I noticed. If you don't have time to look > at them, no problem; I'll try to get to them. But do let me know. Oh boy, you scared me there... But definitively, no, I didn't commit this change yet! As confirmed by: http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/coff-pe-read.c?cvsroot=src Last change on that file dates by January 6. 2012 This was only a RFC, which explains why I did not bother to change the printf call yet! > > 2012-10-15 Pierre Muller <muller@ics.u-strasbg.fr> > > > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > > * coff-pe-read.c (pe_as16): New function. > > (read_pe_exported_syms): Use ordinal of function to > > retrieve correct RVA address of function. > > (pe_text_section_offset): New function. > > > > * windows-tdep.c (windows_xfer_shared_library): Use > > pe_text_section_offset function instead of possibly wrong > > 0x1000 constant for .text sextion offset. > > > @@ -336,26 +344,119 @@ read_pe_exported_syms (struct objfile *o > > { > > /* Pointer to the names vector. */ > > unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); > > + /* Retrieve ordinal value */ > > + > > + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); > > Just a nit: Can we keep the formatting consistent between the two > local variables? In other words, no empty line between the comment > and the variable? Yes, you are of course right here. > > + if (!section_found) > > + { > > + char * forward_name = (char *) (erva + func_rva); > > + char * funcname = (char *) (erva + name_rva); > > + if ((func_rva >= export_rva) > > + && (func_rva < export_rva + export_size)) > > Can you add an empty line between the variable declarations and > the rest of the code. Forgot that ruel again... > Also, the if condition is idented using spaces instead of tabs... I still didn't get a correct way of checking my formatting... > > + printf ("%s is a forward to %s\n", funcname, forward_name); > > I don't think a printf is appropriate, here. Is that meant to be > a warning? I would have like any suggestion about an idea about how to implement such a forward... Something like a function called add_pe_forward_symbol Would it require the definition of a new minimal symbol type? If yes, I wouldn't even know where I should add this new type... > > +CORE_ADDR > > +pe_text_section_offset (struct bfd *abfd) > > Can you add a description of what the function does? I will try to do this. > > + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; > > This is a nit as well, but can you rename opthdr_ofs? I'm a little > confused, as the 's' at the end made me think that it was a plural, > and thus that it was a set of offsets. But looking at the type and > at the code, I am thinking now that this is a short for "offset", > except an 'f' would be missing. How about spelling offset entirely? I basically reused the existing code in the function called read_pe_exported_syms, and, specifically, I kept most of the local variables and used the same names... I quite often also abbreviate offset into ofs, but I am not against renaming 'opthdr_ofs' into 'optional_header_offset'. > > + unsigned char *expdata, *erva; > > Should we be using gdb_byte *, in this case? I'm wondering if we > should be adjusting the pe_get* & pe_as* routines as well... The problem is that it is used both for 'char *' for all the names and for RVA (relative virtual addresses) which are more something like a 32-bit unsigned offset. > > + if (!is_pe32 && !is_pe64) > > + { > > + /* This is not a recognized PE format file. Abort now, because > > + the code is untested on anything else. *FIXME* test on > > + further architectures and loosen or remove this test. */ > > + return 0; > > + } > > I think a complaint would be appropriate, here. And I'm wondering > if there might be a better way to check which PE format it is other > than looking at a string... Again, this is a plain copy of the code in read_pe_exported_syms. > > + if (num_entries < 1) /* No exports. */ > > + { > > + return 0; > > + } > > Formatting: Can you remove the curly braces? For one statement, > our codig style says that we should not be using them. Ditto... > > @@ -387,6 +390,9 @@ windows_xfer_shared_library (const char* > > struct gdbarch *gdbarch, struct obstack *obstack) > > { > > char *p; > > + struct bfd * dll; > > + CORE_ADDR text_offset; > > + CORE_ADDR default_text_offset = 0x1000; > > obstack_grow_str (obstack, "<library name=\""); > > Can you add an empty line after the local variable declarations? > > + if (text_offset != default_text_offset) > > + warning (_("DLL %s has .text section at offset %s\n"),so_name, > > Missing space after the coma (just before 'so_name'). I will try to submit a RFA shortly... Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-10-25 12:21 ` Pierre Muller @ 2012-11-05 17:11 ` Joel Brobecker 2012-11-06 14:31 ` [RFC-v2] " Pierre Muller [not found] ` <50991f5f.8382440a.1100.ffff82abSMTPIN_ADDED@mx.google.com> 0 siblings, 2 replies; 59+ messages in thread From: Joel Brobecker @ 2012-11-05 17:11 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches > Oh boy, you scared me there... But definitively, no, I didn't > commit this change yet! Sorry about the scare. I was looking at the code, and saw identical code, so I figured it got checked in. That's perhaps a clue for us to do more code factoring... > I still didn't get a correct way of checking my formatting... No problemo, I don't think it's a major issue. > > > + printf ("%s is a forward to %s\n", funcname, forward_name); > > > > I don't think a printf is appropriate, here. Is that meant to be > > a warning? > > I would have like any suggestion about an idea about how to > implement such a forward... Something like a function called > add_pe_forward_symbol Would it require the definition of a new > minimal symbol type? If yes, I wouldn't even know where I should > add this new type... Are you saying, remove the need for the printf/warning by implementing the missing feature? If complicated, I'd start with the warning/complaint first, get that checked in, and then think about how to lift the limitation. > I basically reused the existing code in the function called > read_pe_exported_syms, and, specifically, I kept most of the local > variables and used the same names... Let's keep it consistent for now, then... > > > + unsigned char *expdata, *erva; > > > > Should we be using gdb_byte *, in this case? I'm wondering if we > > should be adjusting the pe_get* & pe_as* routines as well... > > The problem is that it is used both for 'char *' > for all the names and for RVA (relative virtual addresses) > which are more something like a 32-bit unsigned offset. I'm not opposed to keeping the consistency, but I think we're going to have to re-evaluate the use of "char *" vs "gdb_byte *" at some point. I think that if you have a buffer of bytes, it's better to use gdb_bytes, as the type was created to deal with this sort of data. Usually, you can't rely on what the buffer contains, because host and target can be different. > > > + if (!is_pe32 && !is_pe64) > > > + { > > > + /* This is not a recognized PE format file. Abort now, because > > > + the code is untested on anything else. *FIXME* test on > > > + further architectures and loosen or remove this test. */ > > > + return 0; > > > + } > > > > I think a complaint would be appropriate, here. And I'm wondering > > if there might be a better way to check which PE format it is other > > than looking at a string... > > Again, this is a plain copy of the code in read_pe_exported_syms. OK, you can keep it that way, at least for now. "plain copy" -> factorize? -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
* [RFC-v2] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-05 17:11 ` Joel Brobecker @ 2012-11-06 14:31 ` Pierre Muller [not found] ` <50991f5f.8382440a.1100.ffff82abSMTPIN_ADDED@mx.google.com> 1 sibling, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-11-06 14:31 UTC (permalink / raw) To: 'Joel Brobecker'; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1522 bytes --] I wrote a new version of the patch that tries to implement most of the things we talked about. It works quite nicely on my windows 7 64-bit using cygwin, mingw32 or a cross-built mingw64 binary. Interestingly, it seems that the mingw64 binary is not really affected by this issue because the 64-bit system DLLs do have a section offset of 0x1000 for .text section, while the 32-bit DLLs have 0x10000. Pierre Muller 2012-11-06 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. [-- Attachment #2: fix-dll-offset-v3.patch --] [-- Type: application/octet-stream, Size: 22797 bytes --] 2012-11-06 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ coff-pe-read.h 6 Nov 2012 13:37:01 -0000 @@ -21,11 +21,17 @@ #if !defined (COFF_PE_READ_H) #define COFF_PE_READ_H +#include "defs.h" struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract for ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.17 diff -u -p -r1.17 coff-pe-read.c --- coff-pe-read.c 4 Jan 2012 08:17:00 -0000 1.17 +++ coff-pe-read.c 6 Nov 2012 13:37:01 -0000 @@ -23,16 +23,26 @@ #include "coff-pe-read.h" +#include <ctype.h> #include "defs.h" #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -40,8 +50,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -99,9 +119,11 @@ get_section_vmas (bfd *abfd, asection *s static void add_pe_exported_sym (char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char ordinal_name[10]; /* Add the stored offset to get the loaded address of the symbol. */ CORE_ADDR vma = func_rva + section_data->vma_offset; @@ -113,39 +135,130 @@ add_pe_exported_sym (char *sym_name, of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); strncpy (qualified_name, dll_name, dll_name_len); qualified_name[dll_name_len] = '!'; strcpy (qualified_name + dll_name_len + 1, sym_name); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + printf_filtered (_("Unknown section type for \"%s\" for entry \"%s\" \ +in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); + prim_record_minimal_symbol (qualified_name, vma, section_data->ms_type, objfile); xfree (qualified_name); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, + prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), + sym_name, dll_name); } -/* Truncate a dll_name at the first dot character. */ +/* Create a minimal symbol entry for an exported forward symbol. + Returns 1 if the forwarded function was found 0 otherwise. */ -static void -read_pe_truncate_name (char *dll_name) +static int +add_pe_forwarded_sym (char *sym_name, char *forward_dll_name, + char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) { - while (*dll_name) + char ordinal_name[10]; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + char *qualified_name = 0; + int dll_name_len = strlen (dll_name); + char *forward_minimal_name = xmalloc (forward_dll_name_len + + forward_func_name_len + 2); + + strncpy (forward_minimal_name, forward_dll_name, forward_dll_name_len); + forward_minimal_name[forward_dll_name_len] = '!'; + strcpy (forward_minimal_name + forward_dll_name_len + 1, forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + + if (!msymbol) { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + int i; + for (i = 0; i < forward_dll_name_len; i++) + forward_minimal_name[i] = tolower (forward_minimal_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + } - else - { - ++dll_name; - } + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding forwarded exported symbol \"%s\" " + "in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_minimal_name); + + xfree (forward_minimal_name); + + if (!msymbol) + { + if (debug_coff_pe_read) + printf_filtered (_("Unable to find function \"%s\" in dll \"%s\" " + ", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; } + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } + + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + + strncpy (qualified_name, dll_name, dll_name_len); + qualified_name[dll_name_len] = '!'; + strcpy (qualified_name + dll_name_len + 1, sym_name); + + prim_record_minimal_symbol (qualified_name, + vma, msymtype, objfile); + + xfree (qualified_name); + + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (sym_name, vma, + msymtype, objfile); + return 1; +} + +/* Truncate a dll_name at the last dot character. */ + +static void +read_pe_truncate_name (char *dll_name) +{ + char * last_point = strrchr (dll_name, '.'); + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -170,6 +283,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -185,35 +306,50 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; struct cleanup *back_to = 0; char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -234,21 +370,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -262,15 +398,30 @@ read_pe_exported_syms (struct objfile *o bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) 8, dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || ((vaddr <= export_opthdrrva) + && (export_opthdrrva < vaddr + vsize))) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + printf_filtered (_("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if ((export_opthdrrva != vaddr) && debug_coff_pe_read) + printf_filtered (_("Wrong value of export RVA for dll \"%s\": " + "0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -284,6 +435,7 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; @@ -298,6 +450,24 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + else + { + otherix++; + section_data = xrealloc (section_data, otherix + * sizeof (struct read_pe_section_data)); + section_data[otherix - 1].section_name = xstrdup (sec_name); + section_data[otherix - 1].rva_start = vaddr; + section_data[otherix - 1].rva_end = vaddr + vsize; + section_data[otherix - 1].vma_offset = 0; + if (characteristics & IMAGE_SCN_CNT_CODE) + section_data[otherix - 1].ms_type = mst_text; + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_data; + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_bss; + else + section_data[otherix - 1].ms_type = mst_unknown; + } } expdata = (unsigned char *) xmalloc (export_size); @@ -321,7 +491,7 @@ read_pe_exported_syms (struct objfile *o /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -331,31 +501,183 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + printf_filtered (_("DLL \"%s\" has %ld export entries, base=%ld\n"), + dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; + + /* First handle forward cases. */ + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strchr (forward_name, '.'); + + if (sep) + { + int len = (int) (sep - forward_name); + forward_dll_name = xmalloc (len + 1); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + if (sep) + xfree (forward_dll_name); + continue; + } - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + static char null_char = '\0'; + + add_pe_exported_sym (&null_char, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + printf_filtered (_("Export name \"%s\" ord. %lu, RVA 0x%lx \ +in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } + if (debug_coff_pe_read) + printf_filtered (_("Finished reading \"%s\", exports %ld, forwards \ +%ld, total %ld/%ld.\n"), + dll_name, nbnormal, nbforward, + nbnormal + nbforward, nexp); /* Discard expdata. */ do_cleanups (back_to); } + +/* Extract for BFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +void _initialize_coff_pe_read (void); + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); +} Index: windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 windows-tdep.c --- windows-tdep.c 5 Jun 2012 13:50:57 -0000 1.16 +++ windows-tdep.c 6 Nov 2012 13:37:01 -0000 @@ -27,6 +27,10 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + gdb_bfd_unref (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50991f5f.8382440a.1100.ffff82abSMTPIN_ADDED@mx.google.com>]
* Re: [RFC-v2] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50991f5f.8382440a.1100.ffff82abSMTPIN_ADDED@mx.google.com> @ 2012-11-07 19:44 ` Pedro Alves 2012-11-08 9:54 ` [RFC-v3] " Pierre Muller [not found] ` <000301cdbd96$f5cd9f10$e168dd30$%muller@ics-cnrs.unistra.fr> 0 siblings, 2 replies; 59+ messages in thread From: Pedro Alves @ 2012-11-07 19:44 UTC (permalink / raw) To: Pierre Muller; +Cc: 'Joel Brobecker', gdb-patches On 11/06/2012 02:31 PM, Pierre Muller wrote: > --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 > +++ coff-pe-read.h 6 Nov 2012 13:37:01 -0000 > @@ -21,11 +21,17 @@ > > #if !defined (COFF_PE_READ_H) > #define COFF_PE_READ_H > +#include "defs.h" The need for this in a header hints at a problem elsewhere. defs.h should always be the first included header. > Index: coff-pe-read.c > =================================================================== > RCS file: /cvs/src/src/gdb/coff-pe-read.c,v > retrieving revision 1.17 > diff -u -p -r1.17 coff-pe-read.c > --- coff-pe-read.c 4 Jan 2012 08:17:00 -0000 1.17 > +++ coff-pe-read.c 6 Nov 2012 13:37:01 -0000 > @@ -23,16 +23,26 @@ > > #include "coff-pe-read.h" > > +#include <ctype.h> > #include "defs.h" There's the problem. I did $ grep "\"defs\.h" *.c -B 3 | grep include | grep -v "\"defs" and $ grep "\"defs\.h" *.h and hopefully caught all cases. Applying in a bit. 2012-11-07 Pedro Alves <palves@redhat.com> * arm-tdep.c: Make defs.h be the first include. * coff-pe-read.c: Ditto. * gnu-nat.c: Ditto. * go32-nat.c: Ditto. * i386-nat.c: Ditto. * ppcnbsd-nat.c: Ditto. * ada-varobj.h: Don't include defs.h. * i386-darwin-tdep.h: Ditto. * i386-nat.h: Ditto. --- gdb/ada-varobj.h | 1 - gdb/arm-tdep.c | 3 ++- gdb/coff-pe-read.c | 3 ++- gdb/gnu-nat.c | 3 ++- gdb/go32-nat.c | 3 ++- gdb/i386-darwin-tdep.h | 1 - gdb/i386-nat.c | 2 +- gdb/i386-nat.h | 2 -- gdb/ppcnbsd-nat.c | 3 ++- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/gdb/ada-varobj.h b/gdb/ada-varobj.h index 2ef1a70..21f4cec 100644 --- a/gdb/ada-varobj.h +++ b/gdb/ada-varobj.h @@ -20,7 +20,6 @@ #ifndef ADA_VAROBJ_H #define ADA_VAROBJ_H -#include "defs.h" #include "varobj.h" struct value; diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 05a030a..fbc2479 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -18,9 +18,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "defs.h" + #include <ctype.h> /* XXX for isupper (). */ -#include "defs.h" #include "frame.h" #include "inferior.h" #include "gdbcmd.h" diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c index 66c7c82..fd55170 100644 --- a/gdb/coff-pe-read.c +++ b/gdb/coff-pe-read.c @@ -21,9 +21,10 @@ Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ +#include "defs.h" + #include "coff-pe-read.h" -#include "defs.h" #include "bfd.h" #include "gdbtypes.h" diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 2ca01e1..b34935e 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "defs.h" + #include <ctype.h> #include <errno.h> #include <limits.h> @@ -52,7 +54,6 @@ #include <portinfo.h> -#include "defs.h" #include "inferior.h" #include "symtab.h" #include "value.h" diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index d848017..ef1da91 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -82,9 +82,10 @@ GDB does not use those as of this writing, and will never need to. */ +#include "defs.h" + #include <fcntl.h> -#include "defs.h" #include "i386-nat.h" #include "inferior.h" #include "gdbthread.h" diff --git a/gdb/i386-darwin-tdep.h b/gdb/i386-darwin-tdep.h index 8be9946..4732b2d 100644 --- a/gdb/i386-darwin-tdep.h +++ b/gdb/i386-darwin-tdep.h @@ -19,7 +19,6 @@ #ifndef __I386_DARWIN_TDEP_H__ #define __I386_DARWIN_TDEP_H__ -#include "defs.h" #include "frame.h" /* Mapping between the general-purpose registers in Darwin x86 thread_state diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c index e7d9b4d..559bc29 100644 --- a/gdb/i386-nat.c +++ b/gdb/i386-nat.c @@ -18,8 +18,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "i386-nat.h" #include "defs.h" +#include "i386-nat.h" #include "breakpoint.h" #include "command.h" #include "gdbcmd.h" diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h index c06993c..be563ef 100644 --- a/gdb/i386-nat.h +++ b/gdb/i386-nat.h @@ -20,8 +20,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "defs.h" - #ifndef I386_NAT_H #define I386_NAT_H 1 diff --git a/gdb/ppcnbsd-nat.c b/gdb/ppcnbsd-nat.c index 8f73283..2b7837d 100644 --- a/gdb/ppcnbsd-nat.c +++ b/gdb/ppcnbsd-nat.c @@ -19,13 +19,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "defs.h" + #include <sys/types.h> #include <sys/ptrace.h> #include <machine/reg.h> #include <machine/frame.h> #include <machine/pcb.h> -#include "defs.h" #include "gdbcore.h" #include "inferior.h" #include "regcache.h" ^ permalink raw reply [flat|nested] 59+ messages in thread
* [RFC-v3] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-07 19:44 ` Pedro Alves @ 2012-11-08 9:54 ` Pierre Muller 2012-11-22 17:30 ` Joel Brobecker [not found] ` <000301cdbd96$f5cd9f10$e168dd30$%muller@ics-cnrs.unistra.fr> 1 sibling, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-11-08 9:54 UTC (permalink / raw) To: 'Pedro Alves', 'Eli Zaretskii' Cc: 'Joel Brobecker', gdb-patches [-- Attachment #1: Type: text/plain, Size: 1456 bytes --] This is an adapted patch after the change by Pedro to always place defs.h as first include header. This is just for convenience as the previous patch probably would create conflicts if applied to up-to-date CVS tree. For Eli, I also attached a second version called fix-dll-branch.patch that applies to gdb_7_5-branch. Comments welcome, Pierre Muller 2012-11-08 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. [-- Attachment #2: fix-dll-offset-v4.patch --] [-- Type: application/octet-stream, Size: 22693 bytes --] 2012-11-08 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ coff-pe-read.h 8 Nov 2012 09:38:55 -0000 @@ -23,9 +23,14 @@ #define COFF_PE_READ_H struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract for ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.18 diff -u -p -r1.18 coff-pe-read.c --- coff-pe-read.c 7 Nov 2012 20:10:13 -0000 1.18 +++ coff-pe-read.c 8 Nov 2012 09:38:55 -0000 @@ -28,12 +28,23 @@ #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" + +#include <ctype.h> /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -41,8 +52,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -100,9 +121,11 @@ get_section_vmas (bfd *abfd, asection *s static void add_pe_exported_sym (char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char ordinal_name[10]; /* Add the stored offset to get the loaded address of the symbol. */ CORE_ADDR vma = func_rva + section_data->vma_offset; @@ -114,39 +137,130 @@ add_pe_exported_sym (char *sym_name, of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); strncpy (qualified_name, dll_name, dll_name_len); qualified_name[dll_name_len] = '!'; strcpy (qualified_name + dll_name_len + 1, sym_name); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + printf_filtered (_("Unknown section type for \"%s\" for entry \"%s\" \ +in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); + prim_record_minimal_symbol (qualified_name, vma, section_data->ms_type, objfile); xfree (qualified_name); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, + prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), + sym_name, dll_name); } -/* Truncate a dll_name at the first dot character. */ +/* Create a minimal symbol entry for an exported forward symbol. + Returns 1 if the forwarded function was found 0 otherwise. */ -static void -read_pe_truncate_name (char *dll_name) +static int +add_pe_forwarded_sym (char *sym_name, char *forward_dll_name, + char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) { - while (*dll_name) + char ordinal_name[10]; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + char *qualified_name = 0; + int dll_name_len = strlen (dll_name); + char *forward_minimal_name = xmalloc (forward_dll_name_len + + forward_func_name_len + 2); + + strncpy (forward_minimal_name, forward_dll_name, forward_dll_name_len); + forward_minimal_name[forward_dll_name_len] = '!'; + strcpy (forward_minimal_name + forward_dll_name_len + 1, forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + + if (!msymbol) { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + int i; + for (i = 0; i < forward_dll_name_len; i++) + forward_minimal_name[i] = tolower (forward_minimal_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + } - else - { - ++dll_name; - } + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding forwarded exported symbol \"%s\" " + "in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_minimal_name); + + xfree (forward_minimal_name); + + if (!msymbol) + { + if (debug_coff_pe_read) + printf_filtered (_("Unable to find function \"%s\" in dll \"%s\" " + ", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; } + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } + + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + + strncpy (qualified_name, dll_name, dll_name_len); + qualified_name[dll_name_len] = '!'; + strcpy (qualified_name + dll_name_len + 1, sym_name); + + prim_record_minimal_symbol (qualified_name, + vma, msymtype, objfile); + + xfree (qualified_name); + + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (sym_name, vma, + msymtype, objfile); + return 1; +} + +/* Truncate a dll_name at the last dot character. */ + +static void +read_pe_truncate_name (char *dll_name) +{ + char * last_point = strrchr (dll_name, '.'); + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -171,6 +285,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -186,35 +308,50 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; struct cleanup *back_to = 0; char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -235,21 +372,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -263,15 +400,30 @@ read_pe_exported_syms (struct objfile *o bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) 8, dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || ((vaddr <= export_opthdrrva) + && (export_opthdrrva < vaddr + vsize))) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + printf_filtered (_("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if ((export_opthdrrva != vaddr) && debug_coff_pe_read) + printf_filtered (_("Wrong value of export RVA for dll \"%s\": " + "0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -285,6 +437,7 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; @@ -299,6 +452,24 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + else + { + otherix++; + section_data = xrealloc (section_data, otherix + * sizeof (struct read_pe_section_data)); + section_data[otherix - 1].section_name = xstrdup (sec_name); + section_data[otherix - 1].rva_start = vaddr; + section_data[otherix - 1].rva_end = vaddr + vsize; + section_data[otherix - 1].vma_offset = 0; + if (characteristics & IMAGE_SCN_CNT_CODE) + section_data[otherix - 1].ms_type = mst_text; + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_data; + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_bss; + else + section_data[otherix - 1].ms_type = mst_unknown; + } } expdata = (unsigned char *) xmalloc (export_size); @@ -322,7 +493,7 @@ read_pe_exported_syms (struct objfile *o /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -332,31 +503,183 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + printf_filtered (_("DLL \"%s\" has %ld export entries, base=%ld\n"), + dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + /* First handle forward cases. */ + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strchr (forward_name, '.'); + + if (sep) + { + int len = (int) (sep - forward_name); + forward_dll_name = xmalloc (len + 1); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + if (sep) + xfree (forward_dll_name); + continue; + } + + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + static char null_char = '\0'; + + add_pe_exported_sym (&null_char, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + printf_filtered (_("Export name \"%s\" ord. %lu, RVA 0x%lx \ +in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } + if (debug_coff_pe_read) + printf_filtered (_("Finished reading \"%s\", exports %ld, forwards \ +%ld, total %ld/%ld.\n"), + dll_name, nbnormal, nbforward, + nbnormal + nbforward, nexp); /* Discard expdata. */ do_cleanups (back_to); } + +/* Extract for BFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +void _initialize_coff_pe_read (void); + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); +} Index: windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 windows-tdep.c --- windows-tdep.c 5 Jun 2012 13:50:57 -0000 1.16 +++ windows-tdep.c 8 Nov 2012 09:38:55 -0000 @@ -27,6 +27,10 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + gdb_bfd_unref (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } [-- Attachment #3: fix-dll-branch.patch --] [-- Type: application/octet-stream, Size: 22811 bytes --] 2012-11-08 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ coff-pe-read.h 8 Nov 2012 09:52:18 -0000 @@ -23,9 +23,14 @@ #define COFF_PE_READ_H struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract for ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.17 diff -u -p -r1.17 coff-pe-read.c --- coff-pe-read.c 4 Jan 2012 08:17:00 -0000 1.17 +++ coff-pe-read.c 8 Nov 2012 09:52:18 -0000 @@ -21,18 +21,29 @@ Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */ +#include "defs.h" #include "coff-pe-read.h" -#include "defs.h" #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" + +#include <ctype.h> /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -40,8 +51,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -99,9 +120,11 @@ get_section_vmas (bfd *abfd, asection *s static void add_pe_exported_sym (char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char ordinal_name[10]; /* Add the stored offset to get the loaded address of the symbol. */ CORE_ADDR vma = func_rva + section_data->vma_offset; @@ -113,39 +136,130 @@ add_pe_exported_sym (char *sym_name, of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); strncpy (qualified_name, dll_name, dll_name_len); qualified_name[dll_name_len] = '!'; strcpy (qualified_name + dll_name_len + 1, sym_name); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + printf_filtered (_("Unknown section type for \"%s\" for entry \"%s\" \ +in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); + prim_record_minimal_symbol (qualified_name, vma, section_data->ms_type, objfile); xfree (qualified_name); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, + prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), + sym_name, dll_name); } -/* Truncate a dll_name at the first dot character. */ +/* Create a minimal symbol entry for an exported forward symbol. + Returns 1 if the forwarded function was found 0 otherwise. */ -static void -read_pe_truncate_name (char *dll_name) +static int +add_pe_forwarded_sym (char *sym_name, char *forward_dll_name, + char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) { - while (*dll_name) + char ordinal_name[10]; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + char *qualified_name = 0; + int dll_name_len = strlen (dll_name); + char *forward_minimal_name = xmalloc (forward_dll_name_len + + forward_func_name_len + 2); + + strncpy (forward_minimal_name, forward_dll_name, forward_dll_name_len); + forward_minimal_name[forward_dll_name_len] = '!'; + strcpy (forward_minimal_name + forward_dll_name_len + 1, forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + + if (!msymbol) { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + int i; + for (i = 0; i < forward_dll_name_len; i++) + forward_minimal_name[i] = tolower (forward_minimal_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + } - else - { - ++dll_name; - } + if (debug_coff_pe_read > 1) + printf_filtered (_("Adding forwarded exported symbol \"%s\" " + "in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_minimal_name); + + xfree (forward_minimal_name); + + if (!msymbol) + { + if (debug_coff_pe_read) + printf_filtered (_("Unable to find function \"%s\" in dll \"%s\" " + ", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; + } + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (*sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; } + + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + + strncpy (qualified_name, dll_name, dll_name_len); + qualified_name[dll_name_len] = '!'; + strcpy (qualified_name + dll_name_len + 1, sym_name); + + prim_record_minimal_symbol (qualified_name, + vma, msymtype, objfile); + + xfree (qualified_name); + + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (sym_name, vma, + msymtype, objfile); + return 1; +} + +/* Truncate a dll_name at the last dot character. */ + +static void +read_pe_truncate_name (char *dll_name) +{ + char * last_point = strrchr (dll_name, '.'); + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -170,6 +284,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -185,35 +307,50 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; struct cleanup *back_to = 0; char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -234,21 +371,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -262,15 +399,30 @@ read_pe_exported_syms (struct objfile *o bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) 8, dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || ((vaddr <= export_opthdrrva) + && (export_opthdrrva < vaddr + vsize))) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + printf_filtered (_("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if ((export_opthdrrva != vaddr) && debug_coff_pe_read) + printf_filtered (_("Wrong value of export RVA for dll \"%s\": " + "0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -284,6 +436,7 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; @@ -298,6 +451,24 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + else + { + otherix++; + section_data = xrealloc (section_data, otherix + * sizeof (struct read_pe_section_data)); + section_data[otherix - 1].section_name = xstrdup (sec_name); + section_data[otherix - 1].rva_start = vaddr; + section_data[otherix - 1].rva_end = vaddr + vsize; + section_data[otherix - 1].vma_offset = 0; + if (characteristics & IMAGE_SCN_CNT_CODE) + section_data[otherix - 1].ms_type = mst_text; + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_data; + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_bss; + else + section_data[otherix - 1].ms_type = mst_unknown; + } } expdata = (unsigned char *) xmalloc (export_size); @@ -321,7 +492,7 @@ read_pe_exported_syms (struct objfile *o /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -331,31 +502,183 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + printf_filtered (_("DLL \"%s\" has %ld export entries, base=%ld\n"), + dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + /* First handle forward cases. */ + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strchr (forward_name, '.'); + + if (sep) + { + int len = (int) (sep - forward_name); + forward_dll_name = xmalloc (len + 1); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + if (sep) + xfree (forward_dll_name); + continue; + } + + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + static char null_char = '\0'; + + add_pe_exported_sym (&null_char, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + printf_filtered (_("Export name \"%s\" ord. %lu, RVA 0x%lx \ +in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } + if (debug_coff_pe_read) + printf_filtered (_("Finished reading \"%s\", exports %ld, forwards \ +%ld, total %ld/%ld.\n"), + dll_name, nbnormal, nbforward, + nbnormal + nbforward, nexp); /* Discard expdata. */ do_cleanups (back_to); } + +/* Extract for BFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +void _initialize_coff_pe_read (void); + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); +} Index: windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.16 diff -u -p -r1.16 windows-tdep.c --- windows-tdep.c 5 Jun 2012 13:50:57 -0000 1.16 +++ windows-tdep.c 8 Nov 2012 09:52:18 -0000 @@ -27,6 +27,9 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +390,22 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + if (dll) + bfd_close (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v3] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-08 9:54 ` [RFC-v3] " Pierre Muller @ 2012-11-22 17:30 ` Joel Brobecker 2012-11-22 17:51 ` Pedro Alves ` (3 more replies) 0 siblings, 4 replies; 59+ messages in thread From: Joel Brobecker @ 2012-11-22 17:30 UTC (permalink / raw) To: Pierre Muller; +Cc: 'Pedro Alves', 'Eli Zaretskii', gdb-patches Hello Pierre, > 2012-11-08 Pierre Muller <muller@sourceware.org> > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > * coff-pe-read.c (debug_coff_pe_read): New static variable. > (struct read_pe_section_data): Add section_name field. > (pe_as16): New function. > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. > (add_pe_exported_sym): Handle unnamed exported function. > (add_pe_forwarded_sym): New function. > (read_pe_exported_syms): Use ordinal of function to > retrieve correct RVA address of function and handle > forwarded symbol. > (pe_text_section_offset): New function. > (show_debug_coff_pe_read): New function. > (_initialize_coff_pe_read): New function adding > 'set/show debug coff_pe_read' commands. > > * windows-tdep.c (windows_xfer_shared_library): Use > pe_text_section_offset function instead of possibly wrong > 0x1000 constant for .text sextion offset. Just a few minor comments... > +/* Extract for ABFD the offset of the .text section. ^^^^^ from? > + Returns default value 0x1000 if information is not found. */ > +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); > +#ifndef IMAGE_SCN_CNT_CODE > +# define IMAGE_SCN_CNT_CODE 0x20 > +#endif > +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA > +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 > +#endif > +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA > +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 > +#endif Do you have an idea of when these macros might not be defined? (and where they are normally coming from?). It'd be nice to add a comment providing the answer to those questions. > static void > add_pe_exported_sym (char *sym_name, > unsigned long func_rva, > + int ordinal, > const struct read_pe_section_data *section_data, > const char *dll_name, struct objfile *objfile) Can you update the funtion documentation to explain what each parameter is? > + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) > + printf_filtered (_("Unknown section type for \"%s\" for entry \"%s\" \ > +in dll \"%s\"\n"), > + section_data->section_name, sym_name, dll_name); There was a discussion in the past about continuations of string messages, and we decided to avoid putting the continuation of the first column, as it affects the -p switch of the diff. I think you can simply do: printf_filtered (_("Unknown section type for \"%s\" for entry" " \"%s\" in dll \"%s\"\n"), section_data->section_name, sym_name, dll_name); > + if (debug_coff_pe_read > 1) > + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), > + sym_name, dll_name); Can you use printf_unfiltered for debug traces? There are several instances of this... > +/* Create a minimal symbol entry for an exported forward symbol. > + Returns 1 if the forwarded function was found 0 otherwise. */ "Return" (our style is more "do this, do that", rather than "does this, does that"). Can you also document what each parameter is? > + int dll_name_len = strlen (dll_name); > + char *forward_minimal_name = xmalloc (forward_dll_name_len + > + forward_func_name_len + 2); Can you use alloca, here? It avoids the need to xfree it later. If you need to xmalloc, then you need to xfree it, and I think that you'd be safer using a cleanup - some of the functions you use might throw an error. > + strncpy (forward_minimal_name, forward_dll_name, forward_dll_name_len); > + forward_minimal_name[forward_dll_name_len] = '!'; > + strcpy (forward_minimal_name + forward_dll_name_len + 1, forward_func_name); You also have the "concat" function, if that makes things a little simple for you. > + int i; > + for (i = 0; i < forward_dll_name_len; i++) Empty line between variable declaration and the rest of the code... > + if (debug_coff_pe_read > 1) > + printf_filtered (_("Adding forwarded exported symbol \"%s\" " > + "in dll \"%s\", pointing to \"%s\"\n"), > + sym_name, dll_name, forward_minimal_name); [l..] > + if (debug_coff_pe_read) > + printf_filtered (_("Unable to find function \"%s\" in dll \"%s\" " > + ", forward of \"%s\" in dll \"%s\"\n"), > + forward_func_name, forward_dll_name, sym_name, > + dll_name); printf_unfiltered. > + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); Same remarks as for "forward_minimal_name"... > + char * last_point = strrchr (dll_name, '.'); > + if (last_point != NULL) > + *last_point = '\0'; Empty line after var declarations... > - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] > - = { {0, 1, 0, mst_text}, > - {0, 1, 0, mst_data}, > - {0, 1, 0, mst_bss} > - }; > + struct read_pe_section_data *section_data; [...] > + section_data = xzalloc (PE_SECTION_TABLE_SIZE > + * sizeof (struct read_pe_section_data)); > + Are we missing a cleanup/xfree? > + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) > + { > + section_data[i].vma_offset = 0; > + section_data[i].rva_start = 1; > + section_data[i].rva_end = 0; > + }; > + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; > + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; > + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; > + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; > + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; > + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; Also, I think it makes it harder to determine what the contents of the table is. I suggest you go back to the static definition above, but updated with the extra field. > - if (vaddr <= export_rva && vaddr + vsize > export_rva) > + if ((strcmp (sname, ".edata") == 0) > + || ((vaddr <= export_opthdrrva) > + && (export_opthdrrva < vaddr + vsize))) The extra parentheses around the numerical comparison operators are unnecessary, I believe. I think the following is equivalent: if (strcmp (sname, ".edata") == 0 || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) > + else if ((export_opthdrrva != vaddr) && debug_coff_pe_read) Same here... > + /* Retrieve ordinal value */ Missing period at end of comment. > + /* This is relatived to ordinal value. */ Missing second space after the period... > + if ((func_rva >= export_rva) > + && (func_rva < export_rva + export_size)) Unnecessary parentheses. > + if (sep) > + { > + int len = (int) (sep - forward_name); > + forward_dll_name = xmalloc (len + 1); Missing empty line after variable declaration. You might want to use a cleanup, just in case something in add_pe_forwarded_sym calls error. > + static char null_char = '\0'; > + > + add_pe_exported_sym (&null_char, func_rva, ordinal, > + section_data, dll_name, objfile); Why does this have to be static? Can you make prim_record_minimal_symbol sym_name parameter a "const", and then declare... const char *empty_name = ""; ... and pass that to add_pe_exported_sym? > + char sname[8]; [...] > + bfd_bread (sname, (bfd_size_type) 8, abfd); Use sizeof (sname) instead of litteral 8? > +static void > +show_debug_coff_pe_read (struct ui_file *file, int from_tty, > + struct cmd_list_element *c, const char *value) This function needs a short description ("implements ..." is good enough). -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v3] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-22 17:30 ` Joel Brobecker @ 2012-11-22 17:51 ` Pedro Alves 2012-11-25 22:50 ` [RFC-v4] " Pierre Muller ` (2 subsequent siblings) 3 siblings, 0 replies; 59+ messages in thread From: Pedro Alves @ 2012-11-22 17:51 UTC (permalink / raw) To: Joel Brobecker; +Cc: Pierre Muller, 'Eli Zaretskii', gdb-patches On 11/22/2012 05:30 PM, Joel Brobecker wrote: >> > + if (debug_coff_pe_read > 1) >> > + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), >> > + sym_name, dll_name); > Can you use printf_unfiltered for debug traces? There are several > instances of this... > Better yet, "fprintf_unfiltered (gdb_stdlog, ". -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-22 17:30 ` Joel Brobecker 2012-11-22 17:51 ` Pedro Alves @ 2012-11-25 22:50 ` Pierre Muller 2012-11-26 17:22 ` Joel Brobecker [not found] ` <15690.5992342674$1353883881@news.gmane.org> [not found] ` <50b2a0d1.c849420a.3a3a.3538SMTPIN_ADDED_BROKEN@mx.google.com> 3 siblings, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-11-25 22:50 UTC (permalink / raw) To: 'Joel Brobecker' Cc: 'Pedro Alves', 'Eli Zaretskii', gdb-patches [-- Attachment #1: Type: text/plain, Size: 11698 bytes --] I attach a new version of my patch to cope with variable offset of .text section for Windows OS DLL's. I hope I have taken all advices of Joel in account. In fact, I was unable to satisfy one suggestion... See below, the answer about my lack of C knowledge. Hoping we are getting closer... Pierre Muller (unchanged) ChangeLog entry: 2012-11-25 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Joel Brobecker > Envoyé : jeudi 22 novembre 2012 18:30 > À : Pierre Muller > Cc : 'Pedro Alves'; 'Eli Zaretskii'; gdb-patches@sourceware.org > Objet : Re: [RFC-v3] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > Hello Pierre, > > > 2012-11-08 Pierre Muller <muller@sourceware.org> > > > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > > * coff-pe-read.c (debug_coff_pe_read): New static variable. > > (struct read_pe_section_data): Add section_name field. > > (pe_as16): New function. > > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. > > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. > > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. > > (add_pe_exported_sym): Handle unnamed exported function. > > (add_pe_forwarded_sym): New function. > > (read_pe_exported_syms): Use ordinal of function to > > retrieve correct RVA address of function and handle > > forwarded symbol. > > (pe_text_section_offset): New function. > > (show_debug_coff_pe_read): New function. > > (_initialize_coff_pe_read): New function adding > > 'set/show debug coff_pe_read' commands. > > > > * windows-tdep.c (windows_xfer_shared_library): Use > > pe_text_section_offset function instead of possibly wrong > > 0x1000 constant for .text sextion offset. > > Just a few minor comments... > > > +/* Extract for ABFD the offset of the .text section. > ^^^^^ from? Of course, thanks for catching this. > > + Returns default value 0x1000 if information is not found. */ > > +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); > > > +#ifndef IMAGE_SCN_CNT_CODE > > +# define IMAGE_SCN_CNT_CODE 0x20 > > +#endif > > +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA > > +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 > > +#endif > > +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA > > +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 > > +#endif > Do you have an idea of when these macros might not be defined? > (and where they are normally coming from?). It'd be nice to add > a comment providing the answer to those questions. These are windows specific macros, but can also be compiled on any other target, if one of the windows target is included in the target list. Thus, I do not really know what type of comment I should add here... > > static void > > add_pe_exported_sym (char *sym_name, > > unsigned long func_rva, > > + int ordinal, > > const struct read_pe_section_data *section_data, > > const char *dll_name, struct objfile *objfile) > > Can you update the funtion documentation to explain what each > parameter is? Done. > > + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) > > + printf_filtered (_("Unknown section type for \"%s\" for entry \"%s\" > \ > > +in dll \"%s\"\n"), > > + section_data->section_name, sym_name, dll_name); > > There was a discussion in the past about continuations of string > messages, and we decided to avoid putting the continuation of the > first column, as it affects the -p switch of the diff. I think you > can simply do: > > printf_filtered (_("Unknown section type for \"%s\" for entry" > " \"%s\" in dll \"%s\"\n"), > section_data->section_name, sym_name, dll_name); Modified as suggested. > > + if (debug_coff_pe_read > 1) > > + printf_filtered (_("Adding exported symbol \"%s\" in dll \"%s\"\n"), > > + sym_name, dll_name); > > Can you use printf_unfiltered for debug traces? There are several > instances of this... Modified using fprintf_unfitered (gdb_stdlog, as per Pedro's suggestion... > > +/* Create a minimal symbol entry for an exported forward symbol. > > + Returns 1 if the forwarded function was found 0 otherwise. */ > > "Return" (our style is more "do this, do that", rather than "does this, > does that"). Can you also document what each parameter is? > > > + int dll_name_len = strlen (dll_name); > > + char *forward_minimal_name = xmalloc (forward_dll_name_len + > > + forward_func_name_len + 2); > > Can you use alloca, here? It avoids the need to xfree it later. > If you need to xmalloc, then you need to xfree it, and I think > that you'd be safer using a cleanup - some of the functions you > use might throw an error. I used alloca here... And tried to use if for the qualified_name too, but that turned out to be a bad idea... The name was apparently still accessed after the function returned, despite the fact that the symbol_name is copied... (This is probably in the hash table, but I didn't completely understand how that works...) > > + strncpy (forward_minimal_name, forward_dll_name, forward_dll_name_len); > > + forward_minimal_name[forward_dll_name_len] = '!'; > > + strcpy (forward_minimal_name + forward_dll_name_len + 1, > forward_func_name); > > You also have the "concat" function, if that makes things a little > simple for you. xsnprintf ("%s!%s", should be even simpler... > > + int i; > > + for (i = 0; i < forward_dll_name_len; i++) > > Empty line between variable declaration and the rest of the code... Still forgetting basics :( Fixed. > > + if (debug_coff_pe_read > 1) > > + printf_filtered (_("Adding forwarded exported symbol \"%s\" " > > + "in dll \"%s\", pointing to \"%s\"\n"), > > + sym_name, dll_name, forward_minimal_name); > [l..] > > + if (debug_coff_pe_read) > > + printf_filtered (_("Unable to find function \"%s\" in dll \"%s\" " > > + ", forward of \"%s\" in dll \"%s\"\n"), > > + forward_func_name, forward_dll_name, sym_name, > > + dll_name); > > printf_unfiltered. > > > + qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); > > Same remarks as for "forward_minimal_name"... OK, I change it to alloca... and did the same in the existing add_pe_exportd_sym function But as I said above, this was a bad idea :( > > + char * last_point = strrchr (dll_name, '.'); > > + if (last_point != NULL) > > + *last_point = '\0'; > > Empty line after var declarations... Fixed. > > - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] > > - = { {0, 1, 0, mst_text}, > > - {0, 1, 0, mst_data}, > > - {0, 1, 0, mst_bss} > > - }; > > + struct read_pe_section_data *section_data; > [...] > > + section_data = xzalloc (PE_SECTION_TABLE_SIZE > > + * sizeof (struct read_pe_section_data)); > > + > > Are we missing a cleanup/xfree? I added some, please check that part, as I have no experience at all with using make_cleanup related functions... In particular, I didn't really get if it is OK to call do_cleanups with a possibly NULL argument... > > + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) > > + { > > + section_data[i].vma_offset = 0; > > + section_data[i].rva_start = 1; > > + section_data[i].rva_end = 0; > > + }; > > + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; > > + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; > > + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; > > + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; > > + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; > > + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; > > Also, I think it makes it harder to determine what the contents of the > table is. I suggest you go back to the static definition above, but > updated with the extra field. Sorry, but here my C knowledge is not sufficent: section_data is now a pointer allocated on heap, how can I reconcile this with the old static definition? > > - if (vaddr <= export_rva && vaddr + vsize > export_rva) > > + if ((strcmp (sname, ".edata") == 0) > > + || ((vaddr <= export_opthdrrva) > > + && (export_opthdrrva < vaddr + vsize))) > > The extra parentheses around the numerical comparison operators are > unnecessary, I believe. I think the following is equivalent: > > if (strcmp (sname, ".edata") == 0 > || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) > > > + else if ((export_opthdrrva != vaddr) && debug_coff_pe_read) > > Same here... > > > + /* Retrieve ordinal value */ > > Missing period at end of comment. > > > + /* This is relatived to ordinal value. */ > > Missing second space after the period... > > > + if ((func_rva >= export_rva) > > + && (func_rva < export_rva + export_size)) > > Unnecessary parentheses. > > > + if (sep) > > + { > > + int len = (int) (sep - forward_name); > > + forward_dll_name = xmalloc (len + 1); > > Missing empty line after variable declaration. You might want to > use a cleanup, just in case something in add_pe_forwarded_sym calls > error. > > > + static char null_char = '\0'; > > + > > + add_pe_exported_sym (&null_char, func_rva, ordinal, > > + section_data, dll_name, objfile); > > Why does this have to be static? > Can you make prim_record_minimal_symbol sym_name parameter a "const", > and then declare... I hope you meant changing add_pe_exported_sym only... I don't want to touch prim_record_minimal_symbol function which is also used in other C sources... I removed the null_char by handling NULL also in add_pe_exportd_sym instead of only supporting a pointer to '\0'. > const char *empty_name = ""; > > ... and pass that to add_pe_exported_sym? > > > > + char sname[8]; > [...] > > + bfd_bread (sname, (bfd_size_type) 8, abfd); > > Use sizeof (sname) instead of litteral 8? Yes... > > +static void > > +show_debug_coff_pe_read (struct ui_file *file, int from_tty, > > + struct cmd_list_element *c, const char *value) > > This function needs a short description ("implements ..." is good > enough). > > -- > Joel [-- Attachment #2: fix-dll-offset-v5.patch --] [-- Type: application/octet-stream, Size: 24412 bytes --] projecttype:gdb revision:HEAD email:muller@ics.u-strasbg.fr 2012-11-25 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (pe_as16): New function. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: src/gdb/coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- src/gdb/coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ src/gdb/coff-pe-read.h 25 Nov 2012 22:36:50 -0000 @@ -23,9 +23,14 @@ #define COFF_PE_READ_H struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract from ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: src/gdb/coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.18 diff -u -p -r1.18 coff-pe-read.c --- src/gdb/coff-pe-read.c 7 Nov 2012 20:10:13 -0000 1.18 +++ src/gdb/coff-pe-read.c 25 Nov 2012 22:36:50 -0000 @@ -28,12 +28,23 @@ #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" + +#include <ctype.h> /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -41,8 +52,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -95,58 +116,147 @@ get_section_vmas (bfd *abfd, asection *s } } \f -/* Create a minimal symbol entry for an exported symbol. */ +/* Create a minimal symbol entry for an exported symbol. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FUNC_RVA contains the Relative Virtual Address of the symbol, + ORDINAL is the ordinal index value of the symbol, + SECTION_DATA contains information about the section in which the + symbol is declared, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ static void add_pe_exported_sym (char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char ordinal_name[10]; + char *qualified_name; /* Add the stored offset to get the loaded address of the symbol. */ - CORE_ADDR vma = func_rva + section_data->vma_offset; - - char *qualified_name = 0; int dll_name_len = strlen (dll_name); /* Generate a (hopefully unique) qualified name using the first part of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ - qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + if (sym_name == NULL || *sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; + } - strncpy (qualified_name, dll_name, dll_name_len); - qualified_name[dll_name_len] = '!'; - strcpy (qualified_name + dll_name_len + 1, sym_name); + qualified_name = xstrprintf ("%s!%s", dll_name, sym_name); - prim_record_minimal_symbol (qualified_name, - vma, section_data->ms_type, objfile); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\"" + " for entry \"%s\" in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); - xfree (qualified_name); + prim_record_minimal_symbol (qualified_name, vma, + section_data->ms_type, objfile); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, - section_data->ms_type, objfile); + prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\"" + " in dll \"%s\"\n"), sym_name, dll_name); } -/* Truncate a dll_name at the first dot character. */ +/* Create a minimal symbol entry for an exported forward symbol. + Return 1 if the forwarded function was found 0 otherwise. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides, + FORWARD_FUNC_NAME is the name of the target symbol in that DLL, + ORDINAL is the ordinal index value of the symbol, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ -static void -read_pe_truncate_name (char *dll_name) + +static int +add_pe_forwarded_sym (char *sym_name, char *forward_dll_name, + char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) { - while (*dll_name) + char ordinal_name[10]; + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + int dll_name_len = strlen (dll_name); + char *qualified_name; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + int forward_len = forward_dll_name_len + forward_func_name_len + 2; + char *forward_minimal_name = alloca (forward_len); + + xsnprintf (forward_minimal_name, forward_len, "%s!%s", forward_dll_name, + forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + + if (!msymbol) { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + int i; - else - { - ++dll_name; - } + for (i = 0; i < forward_dll_name_len; i++) + forward_minimal_name[i] = tolower (forward_minimal_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_minimal_name, + &forward_objfile); + } + + if (!msymbol) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in" + " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; + } + + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol" + " \"%s\" in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_minimal_name); + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (sym_name == NULL || *sym_name == '\0') + { + xsnprintf (ordinal_name, sizeof (ordinal_name), "#%d", ordinal); + sym_name = ordinal_name; } + + qualified_name = xstrprintf ("%s!%s", dll_name, sym_name); + + prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile); + + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (sym_name, vma, msymtype, objfile); + return 1; +} + +/* Truncate a dll_name at the last dot character. */ + +static void +read_pe_truncate_name (char *dll_name) +{ + char * last_point = strrchr (dll_name, '.'); + + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -171,6 +281,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -186,35 +304,53 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; struct cleanup *back_to = 0; + struct cleanup *section_cleanup = 0; char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + section_cleanup = make_cleanup (xfree, section_data); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -235,21 +371,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -261,17 +397,31 @@ read_pe_exported_syms (struct objfile *o unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); - bfd_bread (sname, (bfd_size_type) 8, dll); + bfd_bread (sname, (bfd_size_type) sizeof (sname), dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if (export_opthdrrva != vaddr && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA" + " for dll \"%s\": 0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -285,6 +435,7 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; @@ -299,6 +450,24 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + else + { + otherix++; + section_data = xrealloc (section_data, otherix + * sizeof (struct read_pe_section_data)); + section_data[otherix - 1].section_name = xstrdup (sec_name); + section_data[otherix - 1].rva_start = vaddr; + section_data[otherix - 1].rva_end = vaddr + vsize; + section_data[otherix - 1].vma_offset = 0; + if (characteristics & IMAGE_SCN_CNT_CODE) + section_data[otherix - 1].ms_type = mst_text; + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_data; + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_bss; + else + section_data[otherix - 1].ms_type = mst_unknown; + } } expdata = (unsigned char *) xmalloc (export_size); @@ -322,7 +491,7 @@ read_pe_exported_syms (struct objfile *o /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -332,31 +501,191 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries," + " base=%ld\n"), dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value. */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + /* First handle forward cases. */ + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strrchr (forward_name, '.'); + struct cleanup *sep_cleanup = NULL; + + if (sep) + { + int len = (int) (sep - forward_name); + + forward_dll_name = xmalloc (len + 1); + sep_cleanup = make_cleanup (xfree, forward_dll_name); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + if (sep_cleanup) + do_cleanups (sep_cleanup); + continue; + } + + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + add_pe_exported_sym (NULL, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu," + " RVA 0x%lx in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld," + " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal, + nbforward, nbnormal + nbforward, nexp); /* Discard expdata. */ do_cleanups (back_to); + /* Discard section_data. */ + do_cleanups (section_cleanup); +} + +/* Extract from ABFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +/* Implements "show debug coff_pe_read" command. */ + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ + +void _initialize_coff_pe_read (void); + +/* Adds "Set/show debug coff_pe_read" commands. */ + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); } Index: src/gdb/windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.17 diff -u -p -r1.17 windows-tdep.c --- src/gdb/windows-tdep.c 9 Nov 2012 19:58:02 -0000 1.17 +++ src/gdb/windows-tdep.c 25 Nov 2012 22:36:51 -0000 @@ -27,6 +27,10 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + gdb_bfd_unref (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-25 22:50 ` [RFC-v4] " Pierre Muller @ 2012-11-26 17:22 ` Joel Brobecker 2012-11-26 18:36 ` Tom Tromey 0 siblings, 1 reply; 59+ messages in thread From: Joel Brobecker @ 2012-11-26 17:22 UTC (permalink / raw) To: Pierre Muller, Tom Tromey Cc: 'Pedro Alves', 'Eli Zaretskii', gdb-patches > I used alloca here... And tried to use if for the qualified_name > too, but that turned out to be a bad idea... > > The name was apparently still accessed after the function returned, > despite the fact that the symbol_name is copied... (This is probably > in the hash table, but I didn't completely understand how that > works...) I think you might have unearthed a bug, here. This is the code you propose: + qualified_name = xstrprintf ("%s!%s", dll_name, sym_name); + prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile); Following the code: prim_record_minimal_symbol -> prim_record_minimal_symbol_full with copy_name=1 -> SYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile); And symbol_set_names does: | else | { | lookup_len = len; | lookup_name = linkage_name; | linkage_name_copy = linkage_name; | } | | entry.mangled = (char *) lookup_name; | slot = ((struct demangled_name_entry **) | htab_find_slot (objfile->demangled_names_hash, | &entry, INSERT)); Does it looks like a reference to the string might actually get inserted in the htab if not found, thus defeating the mechanism above? Tom might be better suited to answer that question more authoritatively. In the meantime, one approach that might be equally suitable, but without the bug, is if allocate the name on the objfile obstack, and then call prim_record_minimal_symbol_full directly (I am assuming that objfile can never be null, which seems to be the case by my reading of your patch). > > Are we missing a cleanup/xfree? > > I added some, please check that part, as I have no experience at all > with using make_cleanup related functions... In particular, I didn't > really get if it is OK to call do_cleanups with a possibly NULL > argument... It seems like you're going to have to make some other changes to address the crash that was reported, and Pedro sent you a link to the documentation. So I'll wait for that version before reviewing. Hope that's OK. > > > + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; > > > + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; > > > + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; > > > > Also, I think it makes it harder to determine what the contents of the > > table is. I suggest you go back to the static definition above, but > > updated with the extra field. > > Sorry, but here my C knowledge is not sufficent: > section_data is now a pointer allocated on heap, > how can I reconcile this with the old static definition? I cannot remember what I was thinking (or inhaling) at the time. Probably something good (thinking or inhaling), but now gone. Suggestion withdrawn... > > Can you make prim_record_minimal_symbol sym_name parameter a "const", > > and then declare... > > I hope you meant changing add_pe_exported_sym only... > I don't want to touch prim_record_minimal_symbol function which is also > used in other C sources... > > I removed the null_char by handling NULL also in add_pe_exportd_sym > instead of only supporting a pointer to '\0'. Yes, I meant add_pe_exported_sym, nowing that the only potential issue was with the call to prim_record_minimal_symbol - but not an issue since the name parameter is already a const. Your solution is good, although making the sym_name parameter a const is also an improvement. -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-26 17:22 ` Joel Brobecker @ 2012-11-26 18:36 ` Tom Tromey 2012-11-26 20:58 ` Joel Brobecker 0 siblings, 1 reply; 59+ messages in thread From: Tom Tromey @ 2012-11-26 18:36 UTC (permalink / raw) To: Joel Brobecker Cc: Pierre Muller, 'Pedro Alves', 'Eli Zaretskii', gdb-patches >>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes: Joel> prim_record_minimal_symbol Joel> -> prim_record_minimal_symbol_full with copy_name=1 Joel> -> SYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile); Joel> | else Joel> | { Joel> | lookup_len = len; Joel> | lookup_name = linkage_name; Joel> | linkage_name_copy = linkage_name; Joel> | } Joel> | Joel> | entry.mangled = (char *) lookup_name; Joel> | slot = ((struct demangled_name_entry **) Joel> | htab_find_slot (objfile->demangled_names_hash, Joel> | &entry, INSERT)); Joel> Does it looks like a reference to the string might actually Joel> get inserted in the htab if not found, thus defeating the Joel> mechanism above? Tom might be better suited to answer that Joel> question more authoritatively. Here, 'entry' is used to look in the hash table, but it is not entered into the hash table itself. For that you have to go into the subsequent "*slot == NULL" code; and there it allocates a new entry on the objfile's obstack. There are two cases, but e.g.: *slot = obstack_alloc (&objfile->objfile_obstack, offsetof (struct demangled_name_entry, demangled) + demangled_len + 1); Joel> In the meantime, one approach that might be equally suitable, but Joel> without the bug, is if allocate the name on the objfile obstack, Joel> and then call prim_record_minimal_symbol_full directly I think there's no need; this is what the 'copy_name=1' case is for. Tom ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-26 18:36 ` Tom Tromey @ 2012-11-26 20:58 ` Joel Brobecker 0 siblings, 0 replies; 59+ messages in thread From: Joel Brobecker @ 2012-11-26 20:58 UTC (permalink / raw) To: Tom Tromey Cc: Pierre Muller, 'Pedro Alves', 'Eli Zaretskii', gdb-patches > Here, 'entry' is used to look in the hash table, but it is not entered > into the hash table itself. For that you have to go into the subsequent > "*slot == NULL" code; and there it allocates a new entry on the > objfile's obstack. There are two cases, but e.g.: > > *slot = obstack_alloc (&objfile->objfile_obstack, > offsetof (struct demangled_name_entry, > demangled) > + demangled_len + 1); Ah, I got tricked by the INSERT, but looking at the htab_find_slot documentation, indeed, it clearly explains that the data still needs to be set. I wasn't able to to determine from just reading the code where we might be creating a dangling pointer. > I think there's no need; this is what the 'copy_name=1' case is for. Right. We just need to dig deeper to figure out what it's not working for Pierre... I don't think we want to check in his patch where the xmalloc'ed name does not have a corresponding xfree... Thanks, Tom. -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <15690.5992342674$1353883881@news.gmane.org>]
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <15690.5992342674$1353883881@news.gmane.org> @ 2012-11-26 4:04 ` asmwarrior 2012-11-26 10:14 ` Pierre Muller [not found] ` <50b340fb.0aec440a.1c48.5818SMTPIN_ADDED_BROKEN@mx.google.com> 2012-11-26 16:54 ` Tom Tromey 1 sibling, 2 replies; 59+ messages in thread From: asmwarrior @ 2012-11-26 4:04 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches On 2012-11-26 6:50, Pierre Muller wrote: > I attach a new version of my patch to > cope with variable offset of .text section for Windows OS DLL's. > > I hope I have taken all advices of Joel in account. > In fact, I was unable to satisfy one suggestion... > See below, the answer about my lack of C knowledge. > > > Hoping we are getting closer... > > Pierre Muller > gdb crash here, see the Backtrace: (gdb) file cmd.exe Reading symbols from E:\code\cb\test_code\gdbpython-demo\bin\cmd.exe...done. (gdb) r Starting program: E:\code\cb\test_code\gdbpython-demo\bin\cmd.exe [New Thread 63092.0xf220] warning: HEAP[gdbcvs26.exe]: warning: Invalid Address specified to RtlFreeHeap( 00290000, 04C58028 ) 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 0x7c96f26e in ntdll!RtlpNtMakeTemporaryKey () from C:\WINDOWS\system32\ntdll.dll #3 0x7c970456 in ntdll!RtlpNtMakeTemporaryKey () from C:\WINDOWS\system32\ntdll.dll #4 0x7c94bafc in ntdll!LdrFindEntryForAddress () from C:\WINDOWS\system32\ntdll.dll #5 0x00290000 in ?? () #6 0x7c91a1ba in ntdll!RtlpUnWaitCriticalSection () from C:\WINDOWS\system32\ntdll.dll #7 0x77c2c2de in msvcrt!free () from C:\WINDOWS\system32\msvcrt.dll #8 0x00290000 in ?? () #9 0x004a10dd in do_my_cleanups (pmy_chain=0x4c58020, old_chain=0x4c58020) at ../../gdb/gdb/cleanups.c:155 #10 0x00536102 in read_pe_exported_syms (objfile=0x4bf9008) at ../../gdb/gdb/coff-pe-read.c:595 #11 0x00535158 in coff_symtab_read (objfile=0x4bf9008, nsyms=0, symtab_offset=<optimized out>) at ../../gdb/gdb/coffread.c:1127 #12 coff_symfile_read (objfile=0x4bf9008, symfile_flags=8) at ../../gdb/gdb/coffread.c:610 #13 0x004d39e3 in syms_from_objfile (objfile=0x4bf9008, addrs=<optimized out>, offsets=0x0, num_offsets=0, add_flags=8) at ../../gdb/gdb/symfile.c:999 #14 0x004d3ce0 in symbol_file_add_with_addrs_or_offsets ( abfd=<optimized out>, add_flags=8, addrs=0x4bef518, flags=<optimized out>, parent=0x0, num_offsets=0, offsets=0x0) at ../../gdb/gdb/symfile.c:1105 #15 0x005c27a7 in solib_read_symbols (so=0x30055c8, flags=8) at ../../gdb/gdb/solib.c:608 #16 0x005c2bda in solib_add (pattern=0x0, from_tty=0, target=0x96dfa0 <current_target>, readsyms=1) at ../../gdb/gdb/solib.c:919 #17 0x004dfa5e in post_create_inferior (target=0x96dfa0 <current_target>, from_tty=0) at ../../gdb/gdb/infcmd.c:477 #18 0x004dfc0c in run_command_1 (args=0x0, from_tty=<optimized out>, tbreak_at_main=<optimized out>) at ../../gdb/gdb/infcmd.c:631 #19 0x005ad435 in execute_command (p=0x294331 "", from_tty=1) at ../../gdb/gdb/top.c:491 #20 0x004fd7b6 in command_handler (command=0x294330 "") at ../../gdb/gdb/event-top.c:429 #21 0x004fdf63 in command_line_handler (rl=0x2f98a28 " ") at ../../gdb/gdb/event-top.c:630 #22 0x005debd1 in rl_callback_read_char () at ../../gdb/readline/callback.c:220 #23 0x004fd828 in rl_callback_read_char_wrapper (client_data=0x0) at ../../gdb/gdb/event-top.c:163 #24 0x004fcb24 in handle_file_event (data=...) at ../../gdb/gdb/event-loop.c:827 #25 0x004fcab3 in process_event () at ../../gdb/gdb/event-loop.c:401 #26 process_event () at ../../gdb/gdb/event-loop.c:351 #27 0x004fce35 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 #28 0x004fcf8c in start_event_loop () at ../../gdb/gdb/event-loop.c:490 #29 0x004f7762 in captured_command_loop (data=0x0) at ../../gdb/gdb/main.c:256 #30 0x004f64cb in catch_errors (func=0x4f7750 <captured_command_loop>, func_args=0x0, errstring=0x735b8d <__PRETTY_FUNCTION__.12478+107> "", mask=6) at ../../gdb/gdb/exceptions.c:546 #31 0x004f8266 in captured_main (data=0x2a6fee0) at ../../gdb/gdb/main.c:1032 #32 0x004f64cb in catch_errors (func=0x4f7910 <captured_main>, func_args=0x2a6fee0, errstring=0x735b8d <__PRETTY_FUNCTION__.12478+107> "", mask=6) at ../../gdb/gdb/exceptions.c:546 #33 0x004f8850 in gdb_main (args=0x2a6fee0) at ../../gdb/gdb/main.c:1041 #34 0x006d0218 in main (argc=1, argv=0x293ea0) at ../../gdb/gdb/gdb.c:34 (gdb) ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-26 4:04 ` asmwarrior @ 2012-11-26 10:14 ` Pierre Muller [not found] ` <50b340fb.0aec440a.1c48.5818SMTPIN_ADDED_BROKEN@mx.google.com> 1 sibling, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-11-26 10:14 UTC (permalink / raw) To: 'asmwarrior'; +Cc: gdb-patches Hi all, thanks for trying the patch out... As I commented inside my email, I am not familiar with the make_cleanup/ do_cleanups functions. The crash you see it related to my lack of knowledge in that area, sorry about this. I really do need advice from knowledgeable persons about how to correctly chain several cleanups... Pierre > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de asmwarrior > Envoyé : lundi 26 novembre 2012 05:07 > À : Pierre Muller > Cc : gdb-patches@sourceware.org > Objet : Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > On 2012-11-26 6:50, Pierre Muller wrote: > > I attach a new version of my patch to > > cope with variable offset of .text section for Windows OS DLL's. > > > > I hope I have taken all advices of Joel in account. > > In fact, I was unable to satisfy one suggestion... > > See below, the answer about my lack of C knowledge. > > > > > > Hoping we are getting closer... > > > > Pierre Muller > > > > gdb crash here, see the Backtrace: > > (gdb) file cmd.exe > Reading symbols from E:\code\cb\test_code\gdbpython-demo\bin\cmd.exe...done. > (gdb) r > Starting program: E:\code\cb\test_code\gdbpython-demo\bin\cmd.exe > [New Thread 63092.0xf220] > warning: HEAP[gdbcvs26.exe]: > warning: Invalid Address specified to RtlFreeHeap( 00290000, 04C58028 ) > > > 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 0x7c96f26e in ntdll!RtlpNtMakeTemporaryKey () > from C:\WINDOWS\system32\ntdll.dll > #3 0x7c970456 in ntdll!RtlpNtMakeTemporaryKey () > from C:\WINDOWS\system32\ntdll.dll > #4 0x7c94bafc in ntdll!LdrFindEntryForAddress () > from C:\WINDOWS\system32\ntdll.dll > #5 0x00290000 in ?? () > #6 0x7c91a1ba in ntdll!RtlpUnWaitCriticalSection () > from C:\WINDOWS\system32\ntdll.dll > #7 0x77c2c2de in msvcrt!free () from C:\WINDOWS\system32\msvcrt.dll > #8 0x00290000 in ?? () > #9 0x004a10dd in do_my_cleanups (pmy_chain=0x4c58020, old_chain=0x4c58020) > at ../../gdb/gdb/cleanups.c:155 > #10 0x00536102 in read_pe_exported_syms (objfile=0x4bf9008) > at ../../gdb/gdb/coff-pe-read.c:595 > #11 0x00535158 in coff_symtab_read (objfile=0x4bf9008, nsyms=0, > symtab_offset=<optimized out>) at ../../gdb/gdb/coffread.c:1127 > #12 coff_symfile_read (objfile=0x4bf9008, symfile_flags=8) > at ../../gdb/gdb/coffread.c:610 > #13 0x004d39e3 in syms_from_objfile (objfile=0x4bf9008, > addrs=<optimized out>, offsets=0x0, num_offsets=0, add_flags=8) > at ../../gdb/gdb/symfile.c:999 > #14 0x004d3ce0 in symbol_file_add_with_addrs_or_offsets ( > abfd=<optimized out>, add_flags=8, addrs=0x4bef518, > flags=<optimized out>, parent=0x0, num_offsets=0, offsets=0x0) > at ../../gdb/gdb/symfile.c:1105 > #15 0x005c27a7 in solib_read_symbols (so=0x30055c8, flags=8) > at ../../gdb/gdb/solib.c:608 > #16 0x005c2bda in solib_add (pattern=0x0, from_tty=0, > target=0x96dfa0 <current_target>, readsyms=1) at > ../../gdb/gdb/solib.c:919 > #17 0x004dfa5e in post_create_inferior (target=0x96dfa0 <current_target>, > from_tty=0) at ../../gdb/gdb/infcmd.c:477 > #18 0x004dfc0c in run_command_1 (args=0x0, from_tty=<optimized out>, > tbreak_at_main=<optimized out>) at ../../gdb/gdb/infcmd.c:631 > #19 0x005ad435 in execute_command (p=0x294331 "", from_tty=1) > at ../../gdb/gdb/top.c:491 > #20 0x004fd7b6 in command_handler (command=0x294330 "") > at ../../gdb/gdb/event-top.c:429 > #21 0x004fdf63 in command_line_handler (rl=0x2f98a28 " ") > at ../../gdb/gdb/event-top.c:630 > #22 0x005debd1 in rl_callback_read_char () > at ../../gdb/readline/callback.c:220 > #23 0x004fd828 in rl_callback_read_char_wrapper (client_data=0x0) > at ../../gdb/gdb/event-top.c:163 > #24 0x004fcb24 in handle_file_event (data=...) > at ../../gdb/gdb/event-loop.c:827 > #25 0x004fcab3 in process_event () at ../../gdb/gdb/event-loop.c:401 > #26 process_event () at ../../gdb/gdb/event-loop.c:351 > #27 0x004fce35 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 > #28 0x004fcf8c in start_event_loop () at ../../gdb/gdb/event-loop.c:490 > #29 0x004f7762 in captured_command_loop (data=0x0) at > ../../gdb/gdb/main.c:256 > #30 0x004f64cb in catch_errors (func=0x4f7750 <captured_command_loop>, > func_args=0x0, errstring=0x735b8d <__PRETTY_FUNCTION__.12478+107> "", > mask=6) at ../../gdb/gdb/exceptions.c:546 > #31 0x004f8266 in captured_main (data=0x2a6fee0) at > ../../gdb/gdb/main.c:1032 > #32 0x004f64cb in catch_errors (func=0x4f7910 <captured_main>, > func_args=0x2a6fee0, > errstring=0x735b8d <__PRETTY_FUNCTION__.12478+107> "", mask=6) > at ../../gdb/gdb/exceptions.c:546 > #33 0x004f8850 in gdb_main (args=0x2a6fee0) at ../../gdb/gdb/main.c:1041 > #34 0x006d0218 in main (argc=1, argv=0x293ea0) at ../../gdb/gdb/gdb.c:34 > (gdb) ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50b340fb.0aec440a.1c48.5818SMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50b340fb.0aec440a.1c48.5818SMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-11-26 11:39 ` Pedro Alves 0 siblings, 0 replies; 59+ messages in thread From: Pedro Alves @ 2012-11-26 11:39 UTC (permalink / raw) To: Pierre Muller; +Cc: 'asmwarrior', gdb-patches On 11/26/2012 10:13 AM, Pierre Muller wrote: > Hi all, > > thanks for trying the patch out... > As I commented inside my email, I > am not familiar with the make_cleanup/ do_cleanups > functions. > The crash you see it related to my lack of knowledge in that area, > sorry about this. > I really do need advice from knowledgeable persons > about how to correctly chain several cleanups... It's all described in the gdbint manual: http://sourceware.org/gdb/current/onlinedocs/gdbint/Misc-Guidelines.html#Misc-Guidelines -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <15690.5992342674$1353883881@news.gmane.org> 2012-11-26 4:04 ` asmwarrior @ 2012-11-26 16:54 ` Tom Tromey 2012-11-27 14:59 ` [RFC-v5] " Pierre Muller [not found] ` <42721.1671988063$1354028360@news.gmane.org> 1 sibling, 2 replies; 59+ messages in thread From: Tom Tromey @ 2012-11-26 16:54 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Pedro Alves', 'Eli Zaretskii', gdb-patches >>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes: Joel> Are we missing a cleanup/xfree? Pierre> I added some, please check that part, as I have Pierre> no experience at all with using make_cleanup Pierre> related functions... Pierre> In particular, I didn't really get if it is OK to call Pierre> do_cleanups with a possibly NULL argument... The simplest way to approach cleanups, which I recommend in nearly all cases, is to treat them as block-scoped and to always pass the result of a make_cleanup call to do_cleanups. Try to avoid tricks with conditions and possibly-NULL cleanup pointers, this usually leads to trouble. Pierre> + struct cleanup *section_cleanup = 0; I think there's no need to initialize this, since you re-set it later. Pierre> + section_data = xzalloc (PE_SECTION_TABLE_SIZE Pierre> + * sizeof (struct read_pe_section_data)); Pierre> + Pierre> + section_cleanup = make_cleanup (xfree, section_data); Ok so far, but... Pierre> + section_data = xrealloc (section_data, otherix Pierre> + * sizeof (struct read_pe_section_data)); ... this can free the original pointer. What you want is: section_cleanup = make_cleanup (free_current_contents, §ion_data); This will free the current value of the pointer, instead of capturing the value when the cleanup is made. Pierre> /* Discard expdata. */ Pierre> do_cleanups (back_to); Pierre> + /* Discard section_data. */ Pierre> + do_cleanups (section_cleanup); Cleanups are a stack, so you can just invoke do_cleanups on the outermost one. Just delete the local variable 'back_to'. Tom ^ permalink raw reply [flat|nested] 59+ messages in thread
* [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-26 16:54 ` Tom Tromey @ 2012-11-27 14:59 ` Pierre Muller 2012-12-07 7:10 ` Joel Brobecker [not found] ` <42721.1671988063$1354028360@news.gmane.org> 1 sibling, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-11-27 14:59 UTC (permalink / raw) To: 'Tom Tromey', 'asmwarrior' Cc: 'Joel Brobecker', 'Pedro Alves', 'Eli Zaretskii', gdb-patches [-- Attachment #1: Type: text/plain, Size: 4220 bytes --] Thanks, Tom... it really seems that this is the culprit: I was freeing again already freed memory, which of course created random crashes later. I send here rapidly a new patch version. I really tested the allocation problems by adding allocation + free'ing of each of the first parameters used in prim_record_minimal_symbol and it does seem that freeing of char array doesn't lead to any problem. So the only trouble was related to the reallocation of section_data and seems to be fixed thanks to Tom's proposal. Yuanhui Zhang, could you please check if the new patch suppresses the crash you had when you tried the previous version? Thanks to everyone... Pierre Muller 2012-11-25 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (get_pe_section_index): New function. (struct pe_sections_info): New type. (get_section_vmas): Use new struct pe_sections_info. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_truncate_name): Truncate at last dot. (pe_as16): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Tom Tromey > Envoyé : lundi 26 novembre 2012 17:54 > À : Pierre Muller > Cc : 'Joel Brobecker'; 'Pedro Alves'; 'Eli Zaretskii'; gdb- > patches@sourceware.org > Objet : Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > >>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes: > > Joel> Are we missing a cleanup/xfree? > > Pierre> I added some, please check that part, as I have > Pierre> no experience at all with using make_cleanup > Pierre> related functions... > Pierre> In particular, I didn't really get if it is OK to call > Pierre> do_cleanups with a possibly NULL argument... > > The simplest way to approach cleanups, which I recommend in nearly all > cases, is to treat them as block-scoped and to always pass the result of > a make_cleanup call to do_cleanups. Try to avoid tricks with conditions > and possibly-NULL cleanup pointers, this usually leads to trouble. > > Pierre> + struct cleanup *section_cleanup = 0; > > I think there's no need to initialize this, since you re-set it later. > > Pierre> + section_data = xzalloc (PE_SECTION_TABLE_SIZE > Pierre> + * sizeof (struct read_pe_section_data)); > Pierre> + > Pierre> + section_cleanup = make_cleanup (xfree, section_data); > > Ok so far, but... > > Pierre> + section_data = xrealloc (section_data, otherix > Pierre> + * sizeof (struct read_pe_section_data)); > > ... this can free the original pointer. > > What you want is: > > section_cleanup = make_cleanup (free_current_contents, §ion_data); > > This will free the current value of the pointer, instead of capturing > the value when the cleanup is made. > > Pierre> /* Discard expdata. */ > Pierre> do_cleanups (back_to); > Pierre> + /* Discard section_data. */ > Pierre> + do_cleanups (section_cleanup); > > Cleanups are a stack, so you can just invoke do_cleanups on the > outermost one. Just delete the local variable 'back_to'. > > Tom [-- Attachment #2: fix-dll-offset-v7.patch --] [-- Type: application/octet-stream, Size: 26510 bytes --] 2012-11-25 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (get_pe_section_index): New function. (struct pe_sections_info): New type. (get_section_vmas): Use new struct pe_sections_info. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_truncate_name): Truncate at last dot. (pe_as16): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ coff-pe-read.h 27 Nov 2012 14:45:02 -0000 @@ -23,9 +23,14 @@ #define COFF_PE_READ_H struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract from ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.18 diff -u -p -r1.18 coff-pe-read.c --- coff-pe-read.c 7 Nov 2012 20:10:13 -0000 1.18 +++ coff-pe-read.c 27 Nov 2012 14:45:02 -0000 @@ -28,12 +28,23 @@ #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" + +#include <ctype.h> /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -41,8 +52,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -77,13 +98,40 @@ read_pe_section_index (const char *secti } } +/* Get the index of the named section in our own full arrayi. + text, data and bss in that order. Return PE_SECTION_INDEX_INVALID + if passed an unrecognised section name. */ + +static int +get_pe_section_index (const char *section_name, + struct read_pe_section_data *sections, + int nb_sections) +{ + int i; + for (i = 0; i < nb_sections; i++) + if (strcmp (sections[i].section_name, section_name) == 0) + return i; + return PE_SECTION_INDEX_INVALID; +} + +/* Structure used by get_section_vmas function below + to access section_data array and the size of the array + stored in nb_sections field. */ +struct pe_sections_info +{ + int nb_sections; + struct read_pe_section_data *sections; +}; + /* Record the virtual memory address of a section. */ static void get_section_vmas (bfd *abfd, asection *sectp, void *context) { - struct read_pe_section_data *sections = context; - int sectix = read_pe_section_index (sectp->name); + struct pe_sections_info *data = context; + struct read_pe_section_data *sections = data->sections; + int sectix = get_pe_section_index (sectp->name, sections, + data->nb_sections); if (sectix != PE_SECTION_INDEX_INVALID) { @@ -95,58 +143,148 @@ get_section_vmas (bfd *abfd, asection *s } } \f -/* Create a minimal symbol entry for an exported symbol. */ +/* Create a minimal symbol entry for an exported symbol. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FUNC_RVA contains the Relative Virtual Address of the symbol, + ORDINAL is the ordinal index value of the symbol, + SECTION_DATA contains information about the section in which the + symbol is declared, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ static void -add_pe_exported_sym (char *sym_name, +add_pe_exported_sym (const char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char *qualified_name, *bare_name; /* Add the stored offset to get the loaded address of the symbol. */ - CORE_ADDR vma = func_rva + section_data->vma_offset; - - char *qualified_name = 0; int dll_name_len = strlen (dll_name); /* Generate a (hopefully unique) qualified name using the first part of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ - qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + if (sym_name == NULL || *sym_name == '\0') + bare_name = xstrprintf ("#%d", ordinal); + else + bare_name = xstrdup (sym_name); - strncpy (qualified_name, dll_name, dll_name_len); - qualified_name[dll_name_len] = '!'; - strcpy (qualified_name + dll_name_len + 1, sym_name); + qualified_name = xstrprintf ("%s!%s", dll_name, bare_name); - prim_record_minimal_symbol (qualified_name, - vma, section_data->ms_type, objfile); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\"" + " for entry \"%s\" in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); + prim_record_minimal_symbol (qualified_name, vma, + section_data->ms_type, objfile); + + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (bare_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\"" + " in dll \"%s\"\n"), sym_name, dll_name); xfree (qualified_name); + xfree (bare_name); +} + +/* Create a minimal symbol entry for an exported forward symbol. + Return 1 if the forwarded function was found 0 otherwise. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides, + FORWARD_FUNC_NAME is the name of the target symbol in that DLL, + ORDINAL is the ordinal index value of the symbol, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ + + +static int +add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name, + const char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) +{ + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + int dll_name_len = strlen (dll_name); + char *qualified_name, *bare_name; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + int forward_len = forward_dll_name_len + forward_func_name_len + 2; + char *forward_qualified_name = alloca (forward_len); + + xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name, + forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name, + &forward_objfile); + + if (!msymbol) + { + int i; + + for (i = 0; i < forward_dll_name_len; i++) + forward_qualified_name[i] = tolower (forward_qualified_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name, + &forward_objfile); + } + + if (!msymbol) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in" + " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; + } + + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol" + " \"%s\" in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_qualified_name); + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (sym_name == NULL || *sym_name == '\0') + bare_name = xstrprintf ("#%d", ordinal); + else + bare_name = xstrdup (sym_name); + + qualified_name = xstrprintf ("%s!%s", dll_name, bare_name); + + prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, - section_data->ms_type, objfile); + prim_record_minimal_symbol (bare_name, vma, msymtype, objfile); + xfree (qualified_name); + xfree (bare_name); + + return 1; } -/* Truncate a dll_name at the first dot character. */ +/* Truncate a dll_name at the last dot character. */ static void read_pe_truncate_name (char *dll_name) { - while (*dll_name) - { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + char * last_point = strrchr (dll_name, '.'); - else - { - ++dll_name; - } - } + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -171,6 +309,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -186,35 +332,53 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; + struct pe_sections_info pe_sections_info; - struct cleanup *back_to = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + make_cleanup (free_current_contents, §ion_data); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -235,21 +399,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -261,17 +425,31 @@ read_pe_exported_syms (struct objfile *o unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); - bfd_bread (sname, (bfd_size_type) 8, dll); + bfd_bread (sname, (bfd_size_type) sizeof (sname), dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if (export_opthdrrva != vaddr && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA" + " for dll \"%s\": 0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -285,10 +463,11 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; - sec_name[8] = '\0'; + memset (sec_name, 0, sizeof (sec_name)); bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); bfd_bread (sec_name, (bfd_size_type) 8, dll); @@ -299,10 +478,32 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + else + { + char *name; + + otherix++; + section_data = xrealloc (section_data, otherix + * sizeof (struct read_pe_section_data)); + name = xstrdup (sec_name); + section_data[otherix - 1].section_name = name; + make_cleanup (xfree, name); + section_data[otherix - 1].rva_start = vaddr; + section_data[otherix - 1].rva_end = vaddr + vsize; + section_data[otherix - 1].vma_offset = 0; + if (characteristics & IMAGE_SCN_CNT_CODE) + section_data[otherix - 1].ms_type = mst_text; + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_data; + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + section_data[otherix - 1].ms_type = mst_bss; + else + section_data[otherix - 1].ms_type = mst_unknown; + } } expdata = (unsigned char *) xmalloc (export_size); - back_to = make_cleanup (xfree, expdata); + make_cleanup (xfree, expdata); bfd_seek (dll, (file_ptr) expptr, SEEK_SET); bfd_bread (expdata, (bfd_size_type) export_size, dll); @@ -317,12 +518,15 @@ read_pe_exported_syms (struct objfile *o /* Use internal dll name instead of full pathname. */ dll_name = pe_as32 (expdata + 12) + erva; - bfd_map_over_sections (dll, get_section_vmas, section_data); + pe_sections_info.nb_sections = otherix; + pe_sections_info.sections = section_data; + + bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info); /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -332,31 +536,185 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries," + " base=%ld\n"), dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value. */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; + + /* First handle forward cases. */ + if ((func_rva >= export_rva) + && (func_rva < export_rva + export_size)) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strrchr (forward_name, '.'); + + if (sep) + { + int len = (int) (sep - forward_name); - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + forward_dll_name = alloca (len + 1); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + continue; + } + + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + add_pe_exported_sym (NULL, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu," + " RVA 0x%lx in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } - /* Discard expdata. */ + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld," + " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal, + nbforward, nbnormal + nbforward, nexp); + /* Discard expdata and section_data. */ do_cleanups (back_to); } + +/* Extract from ABFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +/* Implements "show debug coff_pe_read" command. */ + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ + +void _initialize_coff_pe_read (void); + +/* Adds "Set/show debug coff_pe_read" commands. */ + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); +} Index: windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.17 diff -u -p -r1.17 windows-tdep.c --- windows-tdep.c 9 Nov 2012 19:58:02 -0000 1.17 +++ windows-tdep.c 27 Nov 2012 14:45:02 -0000 @@ -27,6 +27,10 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + gdb_bfd_unref (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-27 14:59 ` [RFC-v5] " Pierre Muller @ 2012-12-07 7:10 ` Joel Brobecker 2012-12-07 15:23 ` asmwarrior ` (2 more replies) 0 siblings, 3 replies; 59+ messages in thread From: Joel Brobecker @ 2012-12-07 7:10 UTC (permalink / raw) To: Pierre Muller; +Cc: 'asmwarrior', 'Eli Zaretskii', gdb-patches > 2012-11-25 Pierre Muller <muller@sourceware.org> > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > * coff-pe-read.c (debug_coff_pe_read): New static variable. > (struct read_pe_section_data): Add section_name field. > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. > (get_pe_section_index): New function. > (struct pe_sections_info): New type. > (get_section_vmas): Use new struct pe_sections_info. > (add_pe_exported_sym): Handle unnamed exported function. > (add_pe_forwarded_sym): New function. > (read_pe_truncate_name): Truncate at last dot. > (pe_as16): New function. > (read_pe_exported_syms): Use ordinal of function to > retrieve correct RVA address of function and handle > forwarded symbol. > (pe_text_section_offset): New function. > (show_debug_coff_pe_read): New function. > (_initialize_coff_pe_read): New function adding > 'set/show debug coff_pe_read' commands. > > * windows-tdep.c (windows_xfer_shared_library): Use > pe_text_section_offset function instead of possibly wrong > 0x1000 constant for .text sextion offset. Looks good - OK to commit after the following minor corrections have been applied. For the record, I have tested this patch on x86-windows against AdaCore's GDB testsuite, no regression. Thank you! > +/* Get the index of the named section in our own full arrayi. Small typo at the end if "array". > +get_pe_section_index (const char *section_name, > + struct read_pe_section_data *sections, > + int nb_sections) > +{ > + int i; > + for (i = 0; i < nb_sections; i++) Missing empty line after variable declarations... > + DLL_NAME is the internal name of the DLL file, > + OBJFILE is the objfile struct of DLL_NAME. */ > + > + > +static int > +add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name, Can you delete the second empty line? > + char * last_point = strrchr (dll_name, '.'); No space between '*' and 'last_point'. > + otherix++; > + section_data = xrealloc (section_data, otherix > + * sizeof (struct read_pe_section_data)); > + name = xstrdup (sec_name); > + section_data[otherix - 1].section_name = name; > + make_cleanup (xfree, name); > + section_data[otherix - 1].rva_start = vaddr; > + section_data[otherix - 1].rva_end = vaddr + vsize; > + section_data[otherix - 1].vma_offset = 0; > + if (characteristics & IMAGE_SCN_CNT_CODE) > + section_data[otherix - 1].ms_type = mst_text; > + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) > + section_data[otherix - 1].ms_type = mst_data; > + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) > + section_data[otherix - 1].ms_type = mst_bss; > + else > + section_data[otherix - 1].ms_type = mst_unknown; A possible suggestion: It seems simpler to increment otherix at the end rather than at the beginning, and thus have: section_data = xrealloc (section_data, (otherix + 1) [...]); [...] section_data[otherix].rva_end = vaddr + vsize; section_data[otherix].vma_offset = 0; [...] otherix++; > + /* First handle forward cases. */ > + if ((func_rva >= export_rva) > + && (func_rva < export_rva + export_size)) You don't need the extra parentheses... -- Joel ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 7:10 ` Joel Brobecker @ 2012-12-07 15:23 ` asmwarrior 2012-12-07 15:41 ` Pierre Muller [not found] ` <29545.4593528577$1354894901@news.gmane.org> 2012-12-13 10:48 ` Pierre Muller [not found] ` <37373.4003318988$1355395714@news.gmane.org> 2 siblings, 2 replies; 59+ messages in thread From: asmwarrior @ 2012-12-07 15:23 UTC (permalink / raw) To: Joel Brobecker; +Cc: Pierre Muller, 'Eli Zaretskii', gdb-patches On 2012-12-7 15:10, Joel Brobecker wrote: >> 2012-11-25 Pierre Muller<muller@sourceware.org> >> > >> > * coff-pe-read.h (pe_text_section_offset): Declare new function. >> > * coff-pe-read.c (debug_coff_pe_read): New static variable. >> > (struct read_pe_section_data): Add section_name field. >> > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. >> > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. >> > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. >> > (get_pe_section_index): New function. >> > (struct pe_sections_info): New type. >> > (get_section_vmas): Use new struct pe_sections_info. >> > (add_pe_exported_sym): Handle unnamed exported function. >> > (add_pe_forwarded_sym): New function. >> > (read_pe_truncate_name): Truncate at last dot. >> > (pe_as16): New function. >> > (read_pe_exported_syms): Use ordinal of function to >> > retrieve correct RVA address of function and handle >> > forwarded symbol. >> > (pe_text_section_offset): New function. >> > (show_debug_coff_pe_read): New function. >> > (_initialize_coff_pe_read): New function adding >> > 'set/show debug coff_pe_read' commands. >> > >> > * windows-tdep.c (windows_xfer_shared_library): Use >> > pe_text_section_offset function instead of possibly wrong >> > 0x1000 constant for .text sextion offset. > Looks good I still has crashes, see the debug log and crash bt. I use an un-patched gdb to debug the patched gdb. The debugee gdb crashes when try to run a exe file(codeblocks.exe) E:\code\cb\CB_NIGHTLY>gdb_stable gdb.exe 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 38480.0x95a0] 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 38480.0x9620] [New Thread 38480.0x9028] file e:/code/cb/cleantrunk/src/devel/codeblocks.exe Reading symbols from e:\code\cb\cleantrunk\src\devel\codeblocks.exe...done. <ciations --multiply-instance --no-splash-screen --verbose -p=debugCC (gdb) r Starting program: e:\code\cb\cleantrunk\src\devel\codeblocks.exe --debug-log --n o-dde --no-check-associations --multiply-instance --no-splash-screen --verbose - p=debugCC [New Thread 37324.0x9270] Program received signal SIGSEGV, Segmentation fault. 0x77c47740 in strcmp () from C:\WINDOWS\system32\msvcrt.dll (gdb) bt #0 0x77c47740 in strcmp () from C:\WINDOWS\system32\msvcrt.dll #1 0x00535669 in get_pe_section_index (nb_sections=5, sections=<optimized out>, section_name=0x576b410 ".data") at ../../gdb/gdb/coff-pe-read.c:112 #2 get_section_vmas (abfd=0x30543d0, sectp=0x576c4c0, context=0x2a7f894) at ../../gdb/gdb/coff-pe-read.c:133 #3 0x005f9672 in bfd_map_over_sections (abfd=0x30543d0, operation=0x535630 <get_section_vmas>, user_storage=0x2a7f894) at ../../gdb/bfd/section.c:1329 #4 0x00536066 in read_pe_exported_syms (objfile=0x5834090) at ../../gdb/gdb/coff-pe-read.c:524 #5 0x00535408 in coff_symtab_read (objfile=0x5834090, nsyms=0, symtab_offset=<optimized out>) at ../../gdb/gdb/coffread.c:1127 #6 coff_symfile_read (objfile=0x5834090, symfile_flags=8) at ../../gdb/gdb/coffread.c:610 #7 0x004d3967 in read_symbols (objfile=0x5834090, add_flags=8) at ../../gdb/gdb/symfile.c:885 #8 0x004d340e in syms_from_objfile (objfile=0x5834090, addrs=<optimized out>, offsets=0x0, num_offsets=0, add_flags=8) at ../../gdb/gdb/symfile.c:1020 #9 0x004d36f0 in symbol_file_add_with_addrs_or_offsets ( abfd=<optimized out>, add_flags=8, addrs=0x4d9d640, flags=<optimized out>, parent=0x0, num_offsets=0, offsets=0x0) at ../../gdb/gdb/symfile.c:1123 #10 0x005c2df7 in solib_read_symbols (so=0x2ff7ff8, flags=8) at ../../gdb/gdb/solib.c:608 #11 0x005c322a in solib_add (pattern=0x0, from_tty=0, target=0x96efa0 <current_target>, readsyms=1) at ../../gdb/gdb/solib.c:919 #12 0x004dfcce in post_create_inferior (target=0x96efa0 <current_target>, from_tty=0) at ../../gdb/gdb/infcmd.c:477 #13 0x004dfe7c in run_command_1 (args=0x0, from_tty=<optimized out>, tbreak_at_main=<optimized out>) at ../../gdb/gdb/infcmd.c:631 #14 0x005ada85 in execute_command (p=0x4cfa1b9 "", from_tty=1) at ../../gdb/gdb/top.c:491 #15 0x004fda16 in command_handler (command=0x4cfa1b8 "") at ../../gdb/gdb/event-top.c:429 #16 0x004fe1c3 in command_line_handler (rl=0x292888 " ") at ../../gdb/gdb/event-top.c:630 #17 0x005df1c1 in rl_callback_read_char () at ../../gdb/readline/callback.c:220 #18 0x004fda88 in rl_callback_read_char_wrapper (client_data=0x0) at ../../gdb/gdb/event-top.c:163 #19 0x004fcd84 in handle_file_event (data=...) at ../../gdb/gdb/event-loop.c:827 #20 0x004fcd13 in process_event () at ../../gdb/gdb/event-loop.c:401 #21 process_event () at ../../gdb/gdb/event-loop.c:351 #22 0x004fd095 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 #23 0x004fd1ec in start_event_loop () at ../../gdb/gdb/event-loop.c:490 #24 0x004f79c2 in captured_command_loop (data=0x0) at ../../gdb/gdb/main.c:256 #25 0x004f66eb in catch_errors (func=0x4f79b0 <captured_command_loop>, func_args=0x0, errstring=0x736c0d <__PRETTY_FUNCTION__.12471+203> "", mask=6) at ../../gdb/gdb/exceptions.c:546 #26 0x004f84c6 in captured_main (data=0x2a7fee0) at ../../gdb/gdb/main.c:1032 #27 0x004f66eb in catch_errors (func=0x4f7b70 <captured_main>, func_args=0x2a7fee0, errstring=0x736c0d <__PRETTY_FUNCTION__.12471+203> "", mask=6) at ../../gdb/gdb/exceptions.c:546 #28 0x004f8ab0 in gdb_main (args=0x2a7fee0) at ../../gdb/gdb/main.c:1041 #29 0x006d0878 in main (argc=1, argv=0x293fe0) at ../../gdb/gdb/gdb.c:34 (gdb) frame 1 #1 0x00535669 in get_pe_section_index (nb_sections=5, sections=<optimized out>, section_name=0x576b410 ".data") at ../../gdb/gdb/coff-pe-read.c:112 112 if (strcmp (sections[i].section_name, section_name) == 0) (gdb) p i $1 = <optimized out> (gdb) p sections[i] value has been optimized out (gdb) p section_name $2 = 0x576b410 ".data" (gdb) p sections[i].section_name value has been optimized out (gdb) p nb_sections $3 = 5 (gdb) p sections $4 = <optimized out> (gdb) --------------------------------------------------- But it looks like a lot of variables were optimized out. But it looks like the crash happens here: static int get_pe_section_index (const char *section_name, struct read_pe_section_data *sections, int nb_sections) { int i; for (i = 0; i < nb_sections; i++) if (strcmp (sections[i].section_name, section_name) == 0) return i; return PE_SECTION_INDEX_INVALID; } In the "strcmp" function call. Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 15:23 ` asmwarrior @ 2012-12-07 15:41 ` Pierre Muller [not found] ` <29545.4593528577$1354894901@news.gmane.org> 1 sibling, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-07 15:41 UTC (permalink / raw) To: 'asmwarrior', 'Joel Brobecker' Cc: 'Eli Zaretskii', gdb-patches Hi Yuanhui, thanks for trying to debug this... First, concerning the optimized out problems, it would be easier if you would recompile GDB without optimization: make clean all CFLAGS="-gdwarf-2 -O0" After that, you should get optimized out variables... > Program received signal SIGSEGV, Segmentation fault. > 0x77c47740 in strcmp () from C:\WINDOWS\system32\msvcrt.dll > (gdb) bt > #0 0x77c47740 in strcmp () from C:\WINDOWS\system32\msvcrt.dll > #1 0x00535669 in get_pe_section_index (nb_sections=5, > sections=<optimized out>, section_name=0x576b410 ".data") > at ../../gdb/gdb/coff-pe-read.c:112 > #2 get_section_vmas (abfd=0x30543d0, sectp=0x576c4c0, context=0x2a7f894) > at ../../gdb/gdb/coff-pe-read.c:133 > #3 0x005f9672 in bfd_map_over_sections (abfd=0x30543d0, > operation=0x535630 <get_section_vmas>, user_storage=0x2a7f894) > at ../../gdb/bfd/section.c:1329 > #4 0x00536066 in read_pe_exported_syms (objfile=0x5834090) > at ../../gdb/gdb/coff-pe-read.c:524 > #5 0x00535408 in coff_symtab_read (objfile=0x5834090, nsyms=0, > symtab_offset=<optimized out>) at ../../gdb/gdb/coffread.c:1127 > #6 coff_symfile_read (objfile=0x5834090, symfile_flags=8) > at ../../gdb/gdb/coffread.c:610 > #7 0x004d3967 in read_symbols (objfile=0x5834090, add_flags=8) > at ../../gdb/gdb/symfile.c:885 > #8 0x004d340e in syms_from_objfile (objfile=0x5834090, > addrs=<optimized out>, offsets=0x0, num_offsets=0, add_flags=8) > at ../../gdb/gdb/symfile.c:1020 > #9 0x004d36f0 in symbol_file_add_with_addrs_or_offsets ( > abfd=<optimized out>, add_flags=8, addrs=0x4d9d640, > flags=<optimized out>, parent=0x0, num_offsets=0, offsets=0x0) > at ../../gdb/gdb/symfile.c:1123 > #10 0x005c2df7 in solib_read_symbols (so=0x2ff7ff8, flags=8) > at ../../gdb/gdb/solib.c:608 > #11 0x005c322a in solib_add (pattern=0x0, from_tty=0, > target=0x96efa0 <current_target>, readsyms=1) at > ../../gdb/gdb/solib.c:919 > #12 0x004dfcce in post_create_inferior (target=0x96efa0 <current_target>, > from_tty=0) at ../../gdb/gdb/infcmd.c:477 > #13 0x004dfe7c in run_command_1 (args=0x0, from_tty=<optimized out>, > tbreak_at_main=<optimized out>) at ../../gdb/gdb/infcmd.c:631 > #14 0x005ada85 in execute_command (p=0x4cfa1b9 "", from_tty=1) > at ../../gdb/gdb/top.c:491 > #15 0x004fda16 in command_handler (command=0x4cfa1b8 "") > at ../../gdb/gdb/event-top.c:429 > #16 0x004fe1c3 in command_line_handler (rl=0x292888 " ") > at ../../gdb/gdb/event-top.c:630 > #17 0x005df1c1 in rl_callback_read_char () > at ../../gdb/readline/callback.c:220 > #18 0x004fda88 in rl_callback_read_char_wrapper (client_data=0x0) > at ../../gdb/gdb/event-top.c:163 > #19 0x004fcd84 in handle_file_event (data=...) > at ../../gdb/gdb/event-loop.c:827 > #20 0x004fcd13 in process_event () at ../../gdb/gdb/event-loop.c:401 > #21 process_event () at ../../gdb/gdb/event-loop.c:351 > #22 0x004fd095 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 > #23 0x004fd1ec in start_event_loop () at ../../gdb/gdb/event-loop.c:490 > #24 0x004f79c2 in captured_command_loop (data=0x0) at > ../../gdb/gdb/main.c:256 > #25 0x004f66eb in catch_errors (func=0x4f79b0 <captured_command_loop>, > func_args=0x0, errstring=0x736c0d <__PRETTY_FUNCTION__.12471+203> "", > mask=6) at ../../gdb/gdb/exceptions.c:546 > #26 0x004f84c6 in captured_main (data=0x2a7fee0) at > ../../gdb/gdb/main.c:1032 > #27 0x004f66eb in catch_errors (func=0x4f7b70 <captured_main>, > func_args=0x2a7fee0, > errstring=0x736c0d <__PRETTY_FUNCTION__.12471+203> "", mask=6) > at ../../gdb/gdb/exceptions.c:546 > #28 0x004f8ab0 in gdb_main (args=0x2a7fee0) at ../../gdb/gdb/main.c:1041 > #29 0x006d0878 in main (argc=1, argv=0x293fe0) at ../../gdb/gdb/gdb.c:34 > (gdb) frame 1 > #1 0x00535669 in get_pe_section_index (nb_sections=5, > sections=<optimized out>, section_name=0x576b410 ".data") > at ../../gdb/gdb/coff-pe-read.c:112 > 112 if (strcmp (sections[i].section_name, section_name) == 0) > (gdb) p i > $1 = <optimized out> > (gdb) p sections[i] > value has been optimized out > (gdb) p section_name > $2 = 0x576b410 ".data" > (gdb) p sections[i].section_name > value has been optimized out > (gdb) p nb_sections > $3 = 5 > (gdb) p sections > $4 = <optimized out> > (gdb) > > --------------------------------------------------- > But it looks like a lot of variables were optimized out. > > But it looks like the crash happens here: > > static int > get_pe_section_index (const char *section_name, > struct read_pe_section_data *sections, > int nb_sections) > { > int i; > for (i = 0; i < nb_sections; i++) > if (strcmp (sections[i].section_name, section_name) == 0) > return i; > return PE_SECTION_INDEX_INVALID; > } I also installed CodeBlocks to test if I can reproduce your crash, but I never got any ... Could it be that some weird DLL's have unnamed sections? Could you try to insert if (sections[i] && section[i].name) before > if (strcmp (sections[i].section_name, section_name) == 0) > return i; to confirm that the problem originates here? Thanks again, Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <29545.4593528577$1354894901@news.gmane.org>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <29545.4593528577$1354894901@news.gmane.org> @ 2012-12-07 16:15 ` asmwarrior 2012-12-07 16:27 ` Pierre Muller ` (2 more replies) 0 siblings, 3 replies; 59+ messages in thread From: asmwarrior @ 2012-12-07 16:15 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 2012-12-7 23:40, Pierre Muller wrote: > Hi Yuanhui, > thanks for trying to debug this... > > First, concerning the optimized out problems, > it would be easier if you would recompile > GDB without optimization: > > make clean all CFLAGS="-gdwarf-2 -O0" > > After that, you should get optimized out variables... I will did this if I have more time. > > I also installed CodeBlocks to test if I can reproduce your crash, > but I never got any ... The codeblocks.exe was built myself, which has debug information in it. > > Could it be that some weird DLL's have unnamed > sections? > Could you try to insert > if (sections[i] && section[i].name) > before >> if (strcmp (sections[i].section_name, section_name) == 0) >> return i; > to confirm that the problem originates here? > I add a line: static int get_pe_section_index (const char *section_name, struct read_pe_section_data *sections, int nb_sections) { int i; for (i = 0; i < nb_sections; i++) if (section_name && (§ions[i]) && sections[i].section_name) if (strcmp (sections[i].section_name, section_name) == 0) return i; return PE_SECTION_INDEX_INVALID; } But still the same crash in strcmp(). Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 16:15 ` asmwarrior @ 2012-12-07 16:27 ` Pierre Muller [not found] ` <50c21914.a750420a.2ec3.ffffe4ffSMTPIN_ADDED_BROKEN@mx.google.com> [not found] ` <50c218e5.2850b40a.0281.ffffbef4SMTPIN_ADDED_BROKEN@mx.google.com> 2 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-07 16:27 UTC (permalink / raw) To: 'asmwarrior' Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de asmwarrior > Envoyé : vendredi 7 décembre 2012 17:17 > À : 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-7 23:40, Pierre Muller wrote: > > Hi Yuanhui, > > thanks for trying to debug this... > > > > First, concerning the optimized out problems, > > it would be easier if you would recompile > > GDB without optimization: > > > > make clean all CFLAGS="-gdwarf-2 -O0" > > > > After that, you should get optimized out variables... > > I will did this if I have more time. > > > > > > I also installed CodeBlocks to test if I can reproduce your crash, > > but I never got any ... > > The codeblocks.exe was built myself, which has debug information in it. I tried to recompile the sources, but compilation fails on not found wxWorks headers... Despite the fact that I compiled wxWorks 2.9.4 without problems. > > > > Could it be that some weird DLL's have unnamed > > sections? > > Could you try to insert > > if (sections[i] && section[i].name) > > before > >> if (strcmp (sections[i].section_name, section_name) == 0) > >> return i; > > to confirm that the problem originates here? > > > > I add a line: > static int > get_pe_section_index (const char *section_name, > struct read_pe_section_data *sections, > int nb_sections) > { > int i; > for (i = 0; i < nb_sections; i++) > if (section_name && (§ions[i]) && sections[i].section_name) > if (strcmp (sections[i].section_name, section_name) == 0) > return i; > return PE_SECTION_INDEX_INVALID; > } > > > But still the same crash in strcmp(). Could you try to check that section_name ansd sections array are valid... It will probably require that you recompile GDB :( At the crash point, try to go back to get_pe_section_index frame and do (gdb) print section_name (gdb) print i ... (gdb) print *sections@nb_index This should print the whole array. The problem might also come from some memory corruption elsewhere in my code... Thanks for helping, Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50c21914.a750420a.2ec3.ffffe4ffSMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50c21914.a750420a.2ec3.ffffe4ffSMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-12-07 17:10 ` Pedro Alves 2012-12-07 17:49 ` Pedro Alves 0 siblings, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-07 17:10 UTC (permalink / raw) To: Pierre Muller Cc: 'asmwarrior', 'Joel Brobecker', 'Eli Zaretskii', gdb-patches I haven't tried to grok the patch, but Kai tells me that a section name in PE headers are stored in 8 character arrays, and are not necessarily zero-terminated. He was wondering, and now I am too, if it wouldn't be possible to make use of bfd routines to get at the necessary info, like the .text section offset. E.g., bfd handles the long section name PE extension to coff (see coffcode.h in bfd), though I'm not sure that needs to apply here. -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 17:10 ` Pedro Alves @ 2012-12-07 17:49 ` Pedro Alves 2012-12-13 10:57 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-07 17:49 UTC (permalink / raw) Cc: Pierre Muller, 'asmwarrior', 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 12/07/2012 05:09 PM, Pedro Alves wrote: > I haven't tried to grok the patch, but Kai tells me that a section name in PE headers > are stored in 8 character arrays, and are not necessarily zero-terminated. > He was wondering, and now I am too, if it wouldn't be possible to make use > of bfd routines to get at the necessary info, like the .text section offset. > E.g., bfd handles the long section name PE extension to coff (see coffcode.h in > bfd), though I'm not sure that needs to apply here. Hmm, looking at: > @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* > struct gdbarch *gdbarch, struct obstack *obstack) > { > char *p; > + struct bfd * dll; > + CORE_ADDR text_offset; > + > obstack_grow_str (obstack, "<library name=\""); > p = xml_escape_text (so_name); > obstack_grow_str (obstack, p); > xfree (p); > obstack_grow_str (obstack, "\"><segment address=\""); > - /* The symbols in a dll are offset by 0x1000, which is the > - offset from 0 of the first byte in an image - because of the file > - header and the section alignment. */ > - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); > + dll = gdb_bfd_open_maybe_remote (so_name); > + /* The following calls are OK even if dll is NULL. > + The default value 0x1000 is returned by pe_text_section_offset > + in that case. */ > + text_offset = pe_text_section_offset (dll); > + gdb_bfd_unref (dll); I notice that this only handles native debugging. GDBserver also does the 0x1000 add, see win32-low.c:handle_load_dll. So I'm now actually thinking if the opposite direction may be better. That is, make pe_text_section_offset completely independent of bfd (which it almost is), and put it in a file under common/ so that gdbserver can use it too. -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 17:49 ` Pedro Alves @ 2012-12-13 10:57 ` Pierre Muller 2012-12-13 11:07 ` Pedro Alves 0 siblings, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-12-13 10:57 UTC (permalink / raw) To: 'Pedro Alves' Cc: 'asmwarrior', 'Joel Brobecker', 'Eli Zaretskii', gdb-patches > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pedro Alves > Envoyé : vendredi 7 décembre 2012 18:49 > Cc : Pierre Muller; 'asmwarrior'; '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 12/07/2012 05:09 PM, Pedro Alves wrote: > > I haven't tried to grok the patch, but Kai tells me that a section name in > PE headers > > are stored in 8 character arrays, and are not necessarily zero-terminated. > > He was wondering, and now I am too, if it wouldn't be possible to make use > > of bfd routines to get at the necessary info, like the .text section > offset. > > E.g., bfd handles the long section name PE extension to coff (see > coffcode.h in > > bfd), though I'm not sure that needs to apply here. > > Hmm, looking at: > > > @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* > > struct gdbarch *gdbarch, struct obstack *obstack) > > { > > char *p; > > + struct bfd * dll; > > + CORE_ADDR text_offset; > > + > > obstack_grow_str (obstack, "<library name=\""); > > p = xml_escape_text (so_name); > > obstack_grow_str (obstack, p); > > xfree (p); > > obstack_grow_str (obstack, "\"><segment address=\""); > > - /* The symbols in a dll are offset by 0x1000, which is the > > - offset from 0 of the first byte in an image - because of the file > > - header and the section alignment. */ > > - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); > > + dll = gdb_bfd_open_maybe_remote (so_name); > > + /* The following calls are OK even if dll is NULL. > > + The default value 0x1000 is returned by pe_text_section_offset > > + in that case. */ > > + text_offset = pe_text_section_offset (dll); > > + gdb_bfd_unref (dll); > > I notice that this only handles native debugging. GDBserver also does > the 0x1000 add, see win32-low.c:handle_load_dll. So I'm now actually > thinking if the opposite direction may be better. That is, make > pe_text_section_offset completely independent of bfd (which it almost is), > and put it in a file under common/ so that gdbserver can use it too. Pedro, you are right that my just committed patch does not fix the issue for windows gdbserver... So your idea to share the new function between gdb and gdbserver seemed indeed appealing, but when I looked at the new function pe_text_section_offset it doesn't seem so easy to me to remove bfd dependency... I will try to come up with a fix for gdbserver, but I am not sure it will be soon... Pierre Muller ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 10:57 ` Pierre Muller @ 2012-12-13 11:07 ` Pedro Alves 2012-12-13 11:49 ` Pedro Alves [not found] ` <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr> 0 siblings, 2 replies; 59+ messages in thread From: Pedro Alves @ 2012-12-13 11:07 UTC (permalink / raw) To: Pierre Muller Cc: 'asmwarrior', 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 12/13/2012 10:56 AM, Pierre Muller wrote: > > >> -----Message d'origine----- >> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- >> owner@sourceware.org] De la part de Pedro Alves >> Envoyé : vendredi 7 décembre 2012 18:49 >> Cc : Pierre Muller; 'asmwarrior'; '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 12/07/2012 05:09 PM, Pedro Alves wrote: >>> I haven't tried to grok the patch, but Kai tells me that a section name in >> PE headers >>> are stored in 8 character arrays, and are not necessarily zero-terminated. >>> He was wondering, and now I am too, if it wouldn't be possible to make use >>> of bfd routines to get at the necessary info, like the .text section >> offset. >>> E.g., bfd handles the long section name PE extension to coff (see >> coffcode.h in >>> bfd), though I'm not sure that needs to apply here. >> >> Hmm, looking at: >> ... > Pedro, > you are right that my just committed patch does not > fix the issue for windows gdbserver... > So your idea to share the new function between gdb and gdbserver > seemed indeed appealing, but when I looked at the new function pe_text_section_offset > it doesn't seem so easy to me to remove bfd dependency... > > I will try to come up with a fix for gdbserver, > but I am not sure it will be soon... Thanks. I'm still curious on why you needed the #ifndefs though. There was also the point that section names in PE headers are stored in 8 character arrays, and are not necessarily zero-terminated -- get_pe_section_index does strcmp without accounting for this (grep for SCNNMLEN in bfd). -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 11:07 ` Pedro Alves @ 2012-12-13 11:49 ` Pedro Alves [not found] ` <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr> 1 sibling, 0 replies; 59+ messages in thread From: Pedro Alves @ 2012-12-13 11:49 UTC (permalink / raw) To: Pedro Alves Cc: Pierre Muller, 'asmwarrior', 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 12/13/2012 11:07 AM, Pedro Alves wrote: >> > Pedro, >> > you are right that my just committed patch does not >> > fix the issue for windows gdbserver... >> > So your idea to share the new function between gdb and gdbserver >> > seemed indeed appealing, but when I looked at the new function pe_text_section_offset >> > it doesn't seem so easy to me to remove bfd dependency... It actually looks quite easy to me. >> > >> > I will try to come up with a fix for gdbserver, >> > but I am not sure it will be soon... > Thanks. > CORE_ADDR > pe_text_section_offset (struct bfd *abfd) > > { > unsigned long pe_header_offset, opthdr_ofs, num_entries, i; > unsigned long export_rva, export_size, nsections, secptr, expptr; > unsigned long exp_funcbase; > unsigned char *expdata, *erva; > unsigned long name_rvas, ordinals, nexp, ordbase; > char *dll_name; > int is_pe64 = 0; > int is_pe32 = 0; > char const *target; > > if (!abfd) > return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; > > target = bfd_get_target (abfd); > > is_pe64 = (strcmp (target, "pe-x86-64") == 0 > || strcmp (target, "pei-x86-64") == 0); > is_pe32 = (strcmp (target, "pe-i386") == 0 > || strcmp (target, "pei-i386") == 0 > || strcmp (target, "pe-arm-wince-little") == 0 > || strcmp (target, "pei-arm-wince-little") == 0); > > if (!is_pe32 && !is_pe64) > { > /* This is not a recognized PE format file. Abort now, because > the code is untested on anything else. *FIXME* test on > further architectures and loosen or remove this test. */ > return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; > } Just drop all these is_pe64/is_pe32 checks. They're not really necessary. > /* Get pe_header, optional header and numbers of sections. */ > pe_header_offset = pe_get32 (abfd, 0x3c); > opthdr_ofs = pe_header_offset + 4 + 20; > nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); > secptr = (pe_header_offset + 4 + 20 + > pe_get16 (abfd, pe_header_offset + 4 + 16)); > > /* Get the rva and size of the export section. */ > for (i = 0; i < nsections; i++) > { > char sname[8]; > unsigned long secptr1 = secptr + 40 * i; > unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); > > bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); > bfd_bread (sname, (bfd_size_type) 8, abfd); > if (strcmp (sname, ".text") == 0) > return vaddr; > } All the bfd_seek/bfd_bread calls can be trivially replaced by the equivalent Win32 file handling functions -- note how win32_add_one_solib already has a handy handle open. We can just make handle_load_dll not add the 0x1000 itself, but leave win32_add_one_solib to do it instead. Alternatively, to make the code portable and usable from GDB, use fopen/fread, etc. instead. > return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; > } -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr> @ 2012-12-13 14:32 ` Pedro Alves 2012-12-13 15:17 ` Pierre Muller 2012-12-13 14:33 ` Pedro Alves 1 sibling, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-13 14:32 UTC (permalink / raw) To: Pierre Muller, GDB Patches On 12/13/2012 12:59 PM, Pierre Muller wrote: >> >>> Pedro, >> I'm still curious on why you needed the #ifndefs though. > > Oh, I forgot that one, > I will test without the ifdef's... > These across are defined in mingw32 winnh.h header > and also for cygwin in > /usr/include/aout.h > /usr/include/w32api/winnt.h > as well as in > /usr/include/w32api/ddk/ntimage.h > > and I was afraid that such a header could be included indirectly > by some of the other headers. I don't think that's very likely. That'd mean that coff/pe.h would need guards for its related definitions too. > Below is a patch to remove the unneeded checks... > > 2012-12-13 Pierre Muller <muller@sourceware.org> > > * coff-pe-read.c (IMAGE_SCN_CNT_TEXT, IMAGE_SCN_CNT_INITIALIZED_DATA) > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Remove useless checks > for already defined macros. > > Index: coff-pe-read.c > =================================================================== > RCS file: /cvs/src/src/gdb/coff-pe-read.c,v > retrieving revision 1.19 > diff -u -p -r1.19 coff-pe-read.c > --- coff-pe-read.c 13 Dec 2012 10:44:45 -0000 1.19 > +++ coff-pe-read.c 13 Dec 2012 12:46:09 -0000 > @@ -55,15 +55,9 @@ struct read_pe_section_data > char *section_name; /* Recorded section name. */ > }; > > -#ifndef IMAGE_SCN_CNT_CODE > # define IMAGE_SCN_CNT_CODE 0x20 The spaces in "# define" should be removed too. Okay with that change. > -#endif > -#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA > # define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 > -#endif > -#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA > # define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 > -#endif -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 14:32 ` Pedro Alves @ 2012-12-13 15:17 ` Pierre Muller 0 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-13 15:17 UTC (permalink / raw) To: 'Pedro Alves'; +Cc: 'GDB Patches' > >> I'm still curious on why you needed the #ifndefs though. > > > > Oh, I forgot that one, > > I will test without the ifdef's... > > These across are defined in mingw32 winnh.h header > > and also for cygwin in > > /usr/include/aout.h > > /usr/include/w32api/winnt.h > > as well as in > > /usr/include/w32api/ddk/ntimage.h > > > > and I was afraid that such a header could be included indirectly > > by some of the other headers. > > I don't think that's very likely. That'd mean that coff/pe.h would > need guards for its related definitions too. > > > Below is a patch to remove the unneeded checks... > > > > 2012-12-13 Pierre Muller <muller@sourceware.org> > > > > * coff-pe-read.c (IMAGE_SCN_CNT_TEXT, > IMAGE_SCN_CNT_INITIALIZED_DATA) > > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Remove useless checks > > for already defined macros. > > > > Index: coff-pe-read.c > > =================================================================== > > RCS file: /cvs/src/src/gdb/coff-pe-read.c,v > > retrieving revision 1.19 > > diff -u -p -r1.19 coff-pe-read.c > > --- coff-pe-read.c 13 Dec 2012 10:44:45 -0000 1.19 > > +++ coff-pe-read.c 13 Dec 2012 12:46:09 -0000 > > @@ -55,15 +55,9 @@ struct read_pe_section_data > > char *section_name; /* Recorded section name. */ > > }; > > > > -#ifndef IMAGE_SCN_CNT_CODE > > # define IMAGE_SCN_CNT_CODE 0x20 > > The spaces in "# define" should be removed too. Okay with that change. Thanks committed with your change applied. And my apologies for the cross-post about the coff/internal.h header need. Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr> 2012-12-13 14:32 ` Pedro Alves @ 2012-12-13 14:33 ` Pedro Alves 2012-12-13 14:56 ` Pierre Muller 1 sibling, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-13 14:33 UTC (permalink / raw) To: Pierre Muller, GDB Patches On 12/13/2012 12:59 PM, Pierre Muller wrote: >> > There was also the point that section names in PE headers are stored in 8 >> > character arrays, and are not necessarily zero-terminated -- >> > get_pe_section_index >> > does strcmp without accounting for this (grep for SCNNMLEN in bfd). > the section_name are copied using xstrdup from sec_name > char array of length 9, (indexes 0 to 8) > which is reset using memset for each section. > only the indexes 0to 7 are possibly modified by the bfd_bread call, > so that sec_name[8] always should remain a valid termination of the string, no? I see now, thanks. I think this would make the code a tiny bit clearer. WDYT? 2012-12-13 Pedro Alves <palves@redhat.com> * coff-pe-read.c (read_pe_exported_syms): Use SCNNMLEN instead of hardcoded 8. --- gdb/coff-pe-read.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c index 10bba78..aa4903a 100644 --- a/gdb/coff-pe-read.c +++ b/gdb/coff-pe-read.c @@ -464,12 +464,12 @@ read_pe_exported_syms (struct objfile *objfile) unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long characteristics = pe_get32 (dll, secptr1 + 36); - char sec_name[9]; + char sec_name[SCNNMLEN + 1]; int sectix; memset (sec_name, 0, sizeof (sec_name)); bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); - bfd_bread (sec_name, (bfd_size_type) 8, dll); + bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll); sectix = read_pe_section_index (sec_name); ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 14:33 ` Pedro Alves @ 2012-12-13 14:56 ` Pierre Muller 2012-12-13 15:03 ` Pedro Alves 2012-12-13 15:08 ` Pierre Muller 0 siblings, 2 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-13 14:56 UTC (permalink / raw) To: 'Pedro Alves', 'GDB Patches' > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pedro Alves > Envoyé : jeudi 13 décembre 2012 15:34 > À : Pierre Muller; GDB Patches > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > On 12/13/2012 12:59 PM, Pierre Muller wrote: > >> > There was also the point that section names in PE headers are stored in > 8 > >> > character arrays, and are not necessarily zero-terminated -- > >> > get_pe_section_index > >> > does strcmp without accounting for this (grep for SCNNMLEN in bfd). > > the section_name are copied using xstrdup from sec_name > > char array of length 9, (indexes 0 to 8) > > which is reset using memset for each section. > > only the indexes 0to 7 are possibly modified by the bfd_bread call, > > so that sec_name[8] always should remain a valid termination of the > string, no? > > I see now, thanks. I think this would make the code a tiny bit clearer. > WDYT? Yes, you are right... Maybe removing the memset before and replacing it by a sec_name[SCNNMLEN] = '\0'; after the call to bfd_bread would make it even more clear that you always get a nicely zero terminated string... Pierre > 2012-12-13 Pedro Alves <palves@redhat.com> > > * coff-pe-read.c (read_pe_exported_syms): Use SCNNMLEN instead of > hardcoded 8. > > --- > > gdb/coff-pe-read.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c > index 10bba78..aa4903a 100644 > --- a/gdb/coff-pe-read.c > +++ b/gdb/coff-pe-read.c > @@ -464,12 +464,12 @@ read_pe_exported_syms (struct objfile *objfile) > unsigned long vsize = pe_get32 (dll, secptr1 + 8); > unsigned long vaddr = pe_get32 (dll, secptr1 + 12); > unsigned long characteristics = pe_get32 (dll, secptr1 + 36); > - char sec_name[9]; > + char sec_name[SCNNMLEN + 1]; > int sectix; > > memset (sec_name, 0, sizeof (sec_name)); > bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); > - bfd_bread (sec_name, (bfd_size_type) 8, dll); > + bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll); > > sectix = read_pe_section_index (sec_name); > ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 14:56 ` Pierre Muller @ 2012-12-13 15:03 ` Pedro Alves 2012-12-13 16:43 ` Pedro Alves 2012-12-13 15:08 ` Pierre Muller 1 sibling, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-13 15:03 UTC (permalink / raw) To: Pierre Muller; +Cc: 'GDB Patches' On 12/13/2012 02:56 PM, Pierre Muller wrote: > Maybe removing the memset before and replacing it by a > sec_name[SCNNMLEN] = '\0'; > after the call to bfd_bread > would make it even more clear that you > always get a nicely zero terminated string... That works too. I'm applying this then. 2012-12-13 Pedro Alves <palves@redhat.com> * coff-pe-read.c: Include coff/internal.h. (read_pe_exported_syms): Use SCNNMLEN instead of hardcoded 8. Null terminate buffer explicitly instead of memset the whole buffer. --- gdb/coff-pe-read.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c index 10bba78..9ebff12 100644 --- a/gdb/coff-pe-read.c +++ b/gdb/coff-pe-read.c @@ -34,6 +34,7 @@ #include "symfile.h" #include "objfiles.h" #include "common/common-utils.h" +#include "coff/internal.h" #include <ctype.h> @@ -464,12 +465,12 @@ read_pe_exported_syms (struct objfile *objfile) unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); unsigned long characteristics = pe_get32 (dll, secptr1 + 36); - char sec_name[9]; + char sec_name[SCNNMLEN + 1]; int sectix; - memset (sec_name, 0, sizeof (sec_name)); bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); - bfd_bread (sec_name, (bfd_size_type) 8, dll); + bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll); + sec_name[SCNNMLEN] = '\0'; sectix = read_pe_section_index (sec_name); ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 15:03 ` Pedro Alves @ 2012-12-13 16:43 ` Pedro Alves 2012-12-13 16:54 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-13 16:43 UTC (permalink / raw) To: Pedro Alves; +Cc: Pierre Muller, 'GDB Patches' Oh, the problem was really there, but I got confused pointing at where it is :-). It's in pe_text_section_offset itself: /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) { char sname[8]; unsigned long secptr1 = secptr + 40 * i; unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); bfd_bread (sname, (bfd_size_type) 8, abfd); if (strcmp (sname, ".text") == 0) return vaddr; } So sname should be 9 bytes, and be null terminated after the bfd_bread here too. Want to give it a go? -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 16:43 ` Pedro Alves @ 2012-12-13 16:54 ` Pierre Muller 2012-12-13 16:56 ` Pedro Alves 0 siblings, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-12-13 16:54 UTC (permalink / raw) To: 'Pedro Alves'; +Cc: 'GDB Patches' > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pedro Alves > Envoyé : jeudi 13 décembre 2012 17:43 > À : Pedro Alves > Cc : Pierre Muller; 'GDB Patches' > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > Oh, the problem was really there, but I got confused pointing > at where it is :-). It's in pe_text_section_offset itself: > > /* Get the rva and size of the export section. */ > for (i = 0; i < nsections; i++) > { > char sname[8]; > unsigned long secptr1 = secptr + 40 * i; > unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); > > bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); > bfd_bread (sname, (bfd_size_type) 8, abfd); > if (strcmp (sname, ".text") == 0) > return vaddr; > } > > So sname should be 9 bytes, and be null terminated after the bfd_bread here > too. You are right once more... Strange, because I really thought I copied it from the other function... > Want to give it a go? OK, we were probably lucky because most DLL's have their .text section as first section, so that we never get to 8 char long names... ChangeLog entry: 2012-12-13 Pierre Muller <muller@sourceware.org> * coff-pe-read.c (pe_text_section_offset): Increase size of sname local variable and zero terminate it to avoid possible problems in strcmp. Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.21 diff -u -r1.21 coff-pe-read.c --- coff-pe-read.c 13 Dec 2012 15:11:36 -0000 1.21 +++ coff-pe-read.c 13 Dec 2012 16:49:13 -0000 @@ -672,12 +672,13 @@ pe_text_section_offset (struct bfd *abfd /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) { - char sname[8]; + char sname[SCNNMLEN + 1]; unsigned long secptr1 = secptr + 40 * i; unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); - bfd_bread (sname, (bfd_size_type) 8, abfd); + bfd_bread (sname, (bfd_size_type) SCNNMLEN, abfd); + sname[SCNNMLEN] = '\0'; if (strcmp (sname, ".text") == 0) return vaddr; } ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 16:54 ` Pierre Muller @ 2012-12-13 16:56 ` Pedro Alves 2012-12-13 17:09 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-13 16:56 UTC (permalink / raw) To: Pierre Muller; +Cc: 'GDB Patches' On 12/13/2012 04:54 PM, Pierre Muller wrote: > OK, we were probably lucky because > most DLL's have their .text section as first section, so that we never get to > 8 char long names... Yeah. > > ChangeLog entry: > 2012-12-13 Pierre Muller <muller@sourceware.org> > > * coff-pe-read.c (pe_text_section_offset): Increase size of sname > local variable and zero terminate it to avoid possible problems > in strcmp. Okay, thanks. -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 16:56 ` Pedro Alves @ 2012-12-13 17:09 ` Pierre Muller 0 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-13 17:09 UTC (permalink / raw) To: 'Pedro Alves'; +Cc: 'GDB Patches' Thanks for the persistence in searching! Patch committed, Pierre > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pedro Alves > Envoyé : jeudi 13 décembre 2012 17:56 > À : Pierre Muller > Cc : 'GDB Patches' > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > On 12/13/2012 04:54 PM, Pierre Muller wrote: > > OK, we were probably lucky because > > most DLL's have their .text section as first section, so that we never get > to > > 8 char long names... > > Yeah. > > > > > ChangeLog entry: > > 2012-12-13 Pierre Muller <muller@sourceware.org> > > > > * coff-pe-read.c (pe_text_section_offset): Increase size of sname > > local variable and zero terminate it to avoid possible problems > > in strcmp. > > Okay, thanks. > > -- > Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 14:56 ` Pierre Muller 2012-12-13 15:03 ` Pedro Alves @ 2012-12-13 15:08 ` Pierre Muller 2012-12-13 16:04 ` Pedro Alves 1 sibling, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-12-13 15:08 UTC (permalink / raw) To: 'Pedro Alves', 'GDB Patches' > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pierre Muller > Envoyé : jeudi 13 décembre 2012 15:56 > À : 'Pedro Alves'; 'GDB Patches' > Objet : RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > > > > -----Message d'origine----- > > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > > owner@sourceware.org] De la part de Pedro Alves > > Envoyé : jeudi 13 décembre 2012 15:34 > > À : Pierre Muller; GDB Patches > > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > > __stdcall functions in the inferior) > > > > On 12/13/2012 12:59 PM, Pierre Muller wrote: > > >> > There was also the point that section names in PE headers are stored > in > > 8 > > >> > character arrays, and are not necessarily zero-terminated -- > > >> > get_pe_section_index > > >> > does strcmp without accounting for this (grep for SCNNMLEN in bfd). > > > the section_name are copied using xstrdup from sec_name > > > char array of length 9, (indexes 0 to 8) > > > which is reset using memset for each section. > > > only the indexes 0to 7 are possibly modified by the bfd_bread call, > > > so that sec_name[8] always should remain a valid termination of the > > string, no? > > > > I see now, thanks. I think this would make the code a tiny bit clearer. > > WDYT? > > Yes, you are right... > > Maybe removing the memset before and replacing it by a > sec_name[SCNNMLEN] = '\0'; > after the call to bfd_bread > would make it even more clear that you > always get a nicely zero terminated string... I tried it out, compliation fails because the macro is not set. You would still need to set that macro, which is defined in ../include/coff/internal.h or include that header at start of coff-pe-read.c... Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 15:08 ` Pierre Muller @ 2012-12-13 16:04 ` Pedro Alves 0 siblings, 0 replies; 59+ messages in thread From: Pedro Alves @ 2012-12-13 16:04 UTC (permalink / raw) To: Pierre Muller; +Cc: 'GDB Patches' On 12/13/2012 03:08 PM, Pierre Muller wrote: > I tried it out, compliation fails because the macro is not set. > You would still need to set that macro, > which is defined in ../include/coff/internal.h > or include that header at start of coff-pe-read.c... Yes, you're right. I had noticed that too, but I didn't notice I had posted a version without it. The revision I'm applying has that fixed. Thanks, -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50c218e5.2850b40a.0281.ffffbef4SMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50c218e5.2850b40a.0281.ffffbef4SMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-12-08 14:17 ` asmwarrior 2012-12-08 15:07 ` asmwarrior ` (2 more replies) 0 siblings, 3 replies; 59+ messages in thread From: asmwarrior @ 2012-12-08 14:17 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 2012-12-8 0:27, Pierre Muller wrote: > >> -----Message d'origine----- >> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- >> owner@sourceware.org] De la part de asmwarrior >> Envoyé : vendredi 7 décembre 2012 17:17 >> à : 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-7 23:40, Pierre Muller wrote: >>> Hi Yuanhui, >>> thanks for trying to debug this... >>> >>> First, concerning the optimized out problems, >>> it would be easier if you would recompile >>> GDB without optimization: >>> >>> make clean all CFLAGS="-gdwarf-2 -O0" >>> >>> After that, you should get optimized out variables... >> I will did this if I have more time. >> >> >>> I also installed CodeBlocks to test if I can reproduce your crash, >>> but I never got any ... >> The codeblocks.exe was built myself, which has debug information in it. > I tried to recompile the sources, but > compilation fails on not found wxWorks headers... > Despite the fact that I compiled wxWorks 2.9.4 without problems. Note: Codeblocks currently can build against wxWidgets 2.8.12 library. I think it was not stable to build against wxWidgets 2.9.x. >>> Could it be that some weird DLL's have unnamed >>> sections? >>> Could you try to insert >>> if (sections[i] && section[i].name) >>> before >>>> if (strcmp (sections[i].section_name, section_name) == 0) >>>> return i; >>> to confirm that the problem originates here? >>> >> I add a line: >> static int >> get_pe_section_index (const char *section_name, >> struct read_pe_section_data *sections, >> int nb_sections) >> { >> int i; >> for (i = 0; i < nb_sections; i++) >> if (section_name && (§ions[i]) && sections[i].section_name) >> if (strcmp (sections[i].section_name, section_name) == 0) >> return i; >> return PE_SECTION_INDEX_INVALID; >> } >> >> >> But still the same crash in strcmp(). > Could you try to check that section_name ansd sections array are valid... > It will probably require that you recompile GDB :( Hi, today, I build gdb with "-O0 -g", here is the variables I see when it crashed. Program received signal SIGSEGV, Segmentation fault. 0x77c47784 in strcmp () from C:\WINDOWS\system32\msvcrt.dll (gdb) bt #0 0x77c47784 in strcmp () from C:\WINDOWS\system32\msvcrt.dll #1 0x00562eb9 in get_pe_section_index (section_name=0x5548638 ".data", sections=0x4b33b38, nb_sections=5) at ../../gdb/gdb/coff-pe-read.c:113 #2 0x00562f08 in get_section_vmas (abfd=0x4caede8, sectp=0x55496e8, context=0x285f5ec) at ../../gdb/gdb/coff-pe-read.c:134 #3 0x0064e7ee in bfd_map_over_sections (abfd=0x4caede8, operation=0x562ed5 <get_section_vmas>, user_storage=0x285f5ec) at ../../gdb/bfd/section.c:1329 #4 0x00563d2c in read_pe_exported_syms (objfile=0x5615090) at ../../gdb/gdb/coff-pe-read.c:525 #5 0x00560887 in coff_symtab_read (symtab_offset=0, nsyms=0, objfile=0x5615090) at ../../gdb/gdb/coffread.c:1127 #6 0x0055f660 in coff_symfile_read (objfile=0x5615090, symfile_flags=8) at ../../gdb/gdb/coffread.c:610 #7 0x004f1cc4 in read_symbols (objfile=0x5615090, add_flags=8) at ../../gdb/gdb/symfile.c:885 #8 0x004f203b in syms_from_objfile (objfile=0x5615090, addrs=0x2e04398, offsets=0x0, num_offsets=0, add_flags=8) at ../../gdb/gdb/symfile.c:1020 #9 0x004f2206 in symbol_file_add_with_addrs_or_offsets (abfd=0x4caede8, add_flags=8, addrs=0x2e04398, offsets=0x0, num_offsets=0, flags=2, parent=0x0) at ../../gdb/gdb/symfile.c:1123 #10 0x004f23bf in symbol_file_add_from_bfd (abfd=0x4caede8, add_flags=8, addrs=0x2e04398, flags=2, parent=0x0) at ../../gdb/gdb/symfile.c:1213 #11 0x0060ef33 in solib_read_symbols (so=0x4bdb6b0, flags=8) at ../../gdb/gdb/solib.c:608 #12 0x0060f50d in solib_add (pattern=0x0, from_tty=0, target=0x9ec6c0 <current_target>, readsyms=1) at ../../gdb/gdb/solib.c:919 #13 0x0050146f in post_create_inferior (target=0x9ec6c0 <current_target>, from_tty=0) at ../../gdb/gdb/infcmd.c:477 #14 0x0050175b in run_command_1 (args=0x0, from_tty=1, tbreak_at_main=0) at ../../gdb/gdb/infcmd.c:631 #15 0x005017b0 in run_command (args=0x0, from_tty=1) at ../../gdb/gdb/infcmd.c:645 #16 0x00447794 in do_cfunc (c=0x2d65ed0, args=0x0, from_tty=1) at ../../gdb/gdb/cli/cli-decode.c:114 #17 0x0044a0ce in cmd_func (cmd=0x2d65ed0, args=0x0, from_tty=1) at ../../gdb/gdb/cli/cli-decode.c:1859 #18 0x005f6ebf in execute_command (p=0x294321 "", from_tty=1) at ../../gdb/gdb/top.c:491 #19 0x00524cda in command_handler (command=0x294320 "") at ../../gdb/gdb/event-top.c:429 #20 0x0052524e in command_line_handler (rl=0x2e29fe0 "r") at ../../gdb/gdb/event-top.c:630 #21 0x00630133 in rl_callback_read_char () at ../../gdb/readline/callback.c:220 #22 0x0052481f in rl_callback_read_char_wrapper (client_data=0x0) at ../../gdb/gdb/event-top.c:163 #23 0x00524c04 in stdin_event_handler (error=0, client_data=0x0) at ../../gdb/gdb/event-top.c:369 #24 0x00523df9 in handle_file_event (data=...) at ../../gdb/gdb/event-loop.c:827 #25 0x0052353d in process_event () at ../../gdb/gdb/event-loop.c:401 #26 0x00523602 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 #27 0x00523654 in start_event_loop () at ../../gdb/gdb/event-loop.c:490 #28 0x00524848 in cli_command_loop () at ../../gdb/gdb/event-top.c:176 #29 0x0051cdcf in current_interp_command_loop () at ../../gdb/gdb/interps.c:332 #30 0x0051d6e9 in captured_command_loop (data=0x0) at ../../gdb/gdb/main.c:256 #31 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 #32 0x0051e8c7 in captured_main (data=0x285fee0) at ../../gdb/gdb/main.c:1032 #33 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 #34 0x0051e8fd in gdb_main (args=0x285fee0) at ../../gdb/gdb/main.c:1041 #35 0x00401737 in main (argc=1, argv=0x293ea0) at ../../gdb/gdb/gdb.c:34 (gdb) frame 1 #1 0x00562eb9 in get_pe_section_index (section_name=0x5548638 ".data", sections=0x4b33b38, nb_sections=5) at ../../gdb/gdb/coff-pe-read.c:113 113 if (strcmp (sections[i].section_name, section_name) == 0) (gdb) p section_name $1 = 0x5548638 ".data" (gdb) p i $2 = 2 (gdb) p sections[i].section_name $3 = 0xabababab <Address 0xabababab out of bounds> (gdb) print *sections@nb_sections $4 = {{vma_offset = 2089811968, rva_start = 4096, rva_end = 515802, ms_type = mst_text, section_name = 0x7cd4a0 <coff_sym_fns+64> ".text"}, { vma_offset = 2868903936, rva_start = 2880154539, rva_end = 2880154539, ms_type = mst_unknown, section_name = 0x0}, {vma_offset = 393221, rva_start = 35784515, rva_end = 1920168494, ms_type = 2880110691, section_name = 0xabababab <Address 0xabababab out of bounds>}, { vma_offset = 0, rva_start = 536576, rva_end = 716408, ms_type = mst_data, section_name = 0x4b33b68 ".rsrc"}, {vma_offset = 0, rva_start = 716800, rva_end = 728800, ms_type = mst_data, section_name = 0x4b33be0 ".reloc"}} Look, the value "0xabababab", I'm not sure why gdb report: out of bounds, where does this value come from? Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-08 14:17 ` asmwarrior @ 2012-12-08 15:07 ` asmwarrior 2012-12-08 18:01 ` Pierre Muller [not found] ` <50c38058.03d0d80a.31dd.4e28SMTPIN_ADDED_BROKEN@mx.google.com> 2 siblings, 0 replies; 59+ messages in thread From: asmwarrior @ 2012-12-08 15:07 UTC (permalink / raw) Cc: Pierre Muller, 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 2012-12-8 22:19, asmwarrior wrote: > (gdb) frame 1 > #1 0x00562eb9 in get_pe_section_index (section_name=0x5548638 ".data", > sections=0x4b33b38, nb_sections=5) at ../../gdb/gdb/coff-pe-read.c:113 > 113 if (strcmp (sections[i].section_name, section_name) == 0) > (gdb) p section_name > $1 = 0x5548638 ".data" > (gdb) p i > $2 = 2 > (gdb) p sections[i].section_name > $3 = 0xabababab <Address 0xabababab out of bounds> > (gdb) print *sections@nb_sections > $4 = {{vma_offset = 2089811968, rva_start = 4096, rva_end = 515802, > ms_type = mst_text, section_name = 0x7cd4a0 <coff_sym_fns+64> ".text"}, { > vma_offset = 2868903936, rva_start = 2880154539, rva_end = 2880154539, > ms_type = mst_unknown, section_name = 0x0}, {vma_offset = 393221, > rva_start = 35784515, rva_end = 1920168494, ms_type = 2880110691, > section_name = 0xabababab <Address 0xabababab out of bounds>}, { > vma_offset = 0, rva_start = 536576, rva_end = 716408, ms_type = mst_data, > section_name = 0x4b33b68 ".rsrc"}, {vma_offset = 0, rva_start = 716800, > rva_end = 728800, ms_type = mst_data, section_name = 0x4b33be0 ".reloc"}} > > > > Look, the value "0xabababab", I'm not sure why gdb report: out of bounds, where does this value come from? > Also, see the frame 4's info: (gdb) frame 4 #4 0x00563d2c in read_pe_exported_syms (objfile=0x5615090) at ../../gdb/gdb/coff-pe-read.c:525 525 bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info); (gdb) p dll $7 = (bfd *) 0x4caede8 (gdb) p *dll $8 = {id = 49, filename = 0x5548238 "C:\\WINDOWS\\system32\\ntdll.dll", xvec = 0x84a380 <i386pei_vec>, iostream = 0x77c5fda0 <msvcrt!_iob+288>, iovec = 0x837480 <cache_iovec>, lru_prev = 0x4b66da8, lru_next = 0x4b02950, where = 49758, mtime = 1291907709, ifd = 0, format = bfd_object, direction = read_direction, flags = 65803, origin = 0, proxy_origin = 0, section_htab = {table = 0x5549230, newfunc = 0x64def8 <bfd_section_hash_newfunc>, memory = 0x54b0f40, size = 251, count = 4, entsize = 184, frozen = 0}, sections = 0x5549630, section_last = 0x5549858, section_count = 4, start_address = 2089885944, 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 = 0x5548278, aout_ar_data = 0x5548278, oasys_obj_data = 0x5548278, oasys_ar_data = 0x5548278, coff_obj_data = 0x5548278, pe_obj_data = 0x5548278, xcoff_obj_data = 0x5548278, ecoff_obj_data = 0x5548278, ieee_data = 0x5548278, ieee_ar_data = 0x5548278, srec_data = 0x5548278, verilog_data = 0x5548278, ihex_data = 0x5548278, tekhex_data = 0x5548278, elf_obj_data = 0x5548278, nlm_obj_data = 0x5548278, bout_data = 0x5548278, mmo_data = 0x5548278, sun_core_data = 0x5548278, sco5_core_data = 0x5548278, trad_core_data = 0x5548278, som_data = 0x5548278, hpux_core_data = 0x5548278, hppabsd_core_data = 0x5548278, sgi_core_data = 0x5548278, lynx_core_data = 0x5548278, osf_core_data = 0x5548278, cisco_core_data = 0x5548278, versados_data = 0x5548278, netbsd_core_data = 0x5548278, mach_o_data = 0x5548278, mach_o_fat_data = 0x5548278, plugin_data = 0x5548278, pef_data = 0x5548278, pef_xlib_data = 0x5548278, sym_data = 0x5548278, any = 0x5548278}, usrdata = 0x5548258, memory = 0x54b0df8, 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) So, it crashed on reading the ntdll.dll? ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-08 14:17 ` asmwarrior 2012-12-08 15:07 ` asmwarrior @ 2012-12-08 18:01 ` Pierre Muller [not found] ` <50c38058.03d0d80a.31dd.4e28SMTPIN_ADDED_BROKEN@mx.google.com> 2 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-08 18:01 UTC (permalink / raw) To: 'asmwarrior' Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches Hi Yuanhui, thanks again for trying to debug that problem... > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de asmwarrior > Envoyé : samedi 8 décembre 2012 15:20 > À : 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-8 0:27, Pierre Muller wrote: > > > >> -----Message d'origine----- > >> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > >> owner@sourceware.org] De la part de asmwarrior > >> Envoyé : vendredi 7 décembre 2012 17:17 > >> À : 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-7 23:40, Pierre Muller wrote: > >>> Hi Yuanhui, > >>> thanks for trying to debug this... > >>> > >>> First, concerning the optimized out problems, > >>> it would be easier if you would recompile > >>> GDB without optimization: > >>> > >>> make clean all CFLAGS="-gdwarf-2 -O0" > >>> > >>> After that, you should get optimized out variables... > >> I will did this if I have more time. > >> > >> > >>> I also installed CodeBlocks to test if I can reproduce your crash, > >>> but I never got any ... > >> The codeblocks.exe was built myself, which has debug information in it. > > I tried to recompile the sources, but > > compilation fails on not found wxWorks headers... > > Despite the fact that I compiled wxWorks 2.9.4 without problems. > Note: Codeblocks currently can build against wxWidgets 2.8.12 library. I > think it was not stable to build against wxWidgets 2.9.x. Thanks for the information. > >>> Could it be that some weird DLL's have unnamed > >>> sections? > >>> Could you try to insert > >>> if (sections[i] && section[i].name) > >>> before > >>>> if (strcmp (sections[i].section_name, section_name) == 0) > >>>> return i; > >>> to confirm that the problem originates here? > >>> > >> I add a line: > >> static int > >> get_pe_section_index (const char *section_name, > >> struct read_pe_section_data *sections, > >> int nb_sections) > >> { > >> int i; > >> for (i = 0; i < nb_sections; i++) > >> if (section_name && (§ions[i]) && sections[i].section_name) > >> if (strcmp (sections[i].section_name, section_name) == 0) > >> return i; > >> return PE_SECTION_INDEX_INVALID; > >> } > >> > >> > >> But still the same crash in strcmp(). > > Could you try to check that section_name ansd sections array are > valid... > > It will probably require that you recompile GDB :( > Hi, today, I build gdb with "-O0 -g", here is the variables I see when it > crashed. > > Program received signal SIGSEGV, Segmentation fault. > 0x77c47784 in strcmp () from C:\WINDOWS\system32\msvcrt.dll > (gdb) bt > #0 0x77c47784 in strcmp () from C:\WINDOWS\system32\msvcrt.dll > #1 0x00562eb9 in get_pe_section_index (section_name=0x5548638 ".data", > sections=0x4b33b38, nb_sections=5) at ../../gdb/gdb/coff-pe-read.c:113 > #2 0x00562f08 in get_section_vmas (abfd=0x4caede8, sectp=0x55496e8, > context=0x285f5ec) at ../../gdb/gdb/coff-pe-read.c:134 > #3 0x0064e7ee in bfd_map_over_sections (abfd=0x4caede8, > operation=0x562ed5 <get_section_vmas>, user_storage=0x285f5ec) > at ../../gdb/bfd/section.c:1329 > #4 0x00563d2c in read_pe_exported_syms (objfile=0x5615090) > at ../../gdb/gdb/coff-pe-read.c:525 > #5 0x00560887 in coff_symtab_read (symtab_offset=0, nsyms=0, > objfile=0x5615090) at ../../gdb/gdb/coffread.c:1127 > #6 0x0055f660 in coff_symfile_read (objfile=0x5615090, symfile_flags=8) > at ../../gdb/gdb/coffread.c:610 > #7 0x004f1cc4 in read_symbols (objfile=0x5615090, add_flags=8) > at ../../gdb/gdb/symfile.c:885 > #8 0x004f203b in syms_from_objfile (objfile=0x5615090, addrs=0x2e04398, > offsets=0x0, num_offsets=0, add_flags=8) at > ../../gdb/gdb/symfile.c:1020 > #9 0x004f2206 in symbol_file_add_with_addrs_or_offsets (abfd=0x4caede8, > add_flags=8, addrs=0x2e04398, offsets=0x0, num_offsets=0, flags=2, > parent=0x0) at ../../gdb/gdb/symfile.c:1123 > #10 0x004f23bf in symbol_file_add_from_bfd (abfd=0x4caede8, add_flags=8, > addrs=0x2e04398, flags=2, parent=0x0) at ../../gdb/gdb/symfile.c:1213 > #11 0x0060ef33 in solib_read_symbols (so=0x4bdb6b0, flags=8) > at ../../gdb/gdb/solib.c:608 > #12 0x0060f50d in solib_add (pattern=0x0, from_tty=0, > target=0x9ec6c0 <current_target>, readsyms=1) at > ../../gdb/gdb/solib.c:919 > #13 0x0050146f in post_create_inferior (target=0x9ec6c0 <current_target>, > from_tty=0) at ../../gdb/gdb/infcmd.c:477 > #14 0x0050175b in run_command_1 (args=0x0, from_tty=1, tbreak_at_main=0) > at ../../gdb/gdb/infcmd.c:631 > #15 0x005017b0 in run_command (args=0x0, from_tty=1) > at ../../gdb/gdb/infcmd.c:645 > #16 0x00447794 in do_cfunc (c=0x2d65ed0, args=0x0, from_tty=1) > at ../../gdb/gdb/cli/cli-decode.c:114 > #17 0x0044a0ce in cmd_func (cmd=0x2d65ed0, args=0x0, from_tty=1) > at ../../gdb/gdb/cli/cli-decode.c:1859 > #18 0x005f6ebf in execute_command (p=0x294321 "", from_tty=1) > at ../../gdb/gdb/top.c:491 > #19 0x00524cda in command_handler (command=0x294320 "") > at ../../gdb/gdb/event-top.c:429 > #20 0x0052524e in command_line_handler (rl=0x2e29fe0 "r") > at ../../gdb/gdb/event-top.c:630 > #21 0x00630133 in rl_callback_read_char () > at ../../gdb/readline/callback.c:220 > #22 0x0052481f in rl_callback_read_char_wrapper (client_data=0x0) > at ../../gdb/gdb/event-top.c:163 > #23 0x00524c04 in stdin_event_handler (error=0, client_data=0x0) > at ../../gdb/gdb/event-top.c:369 > #24 0x00523df9 in handle_file_event (data=...) > at ../../gdb/gdb/event-loop.c:827 > #25 0x0052353d in process_event () at ../../gdb/gdb/event-loop.c:401 > #26 0x00523602 in gdb_do_one_event () at ../../gdb/gdb/event-loop.c:465 > #27 0x00523654 in start_event_loop () at ../../gdb/gdb/event-loop.c:490 > #28 0x00524848 in cli_command_loop () at ../../gdb/gdb/event-top.c:176 > #29 0x0051cdcf in current_interp_command_loop () > at ../../gdb/gdb/interps.c:332 > #30 0x0051d6e9 in captured_command_loop (data=0x0) at > ../../gdb/gdb/main.c:256 > #31 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 > #32 0x0051e8c7 in captured_main (data=0x285fee0) at > ../../gdb/gdb/main.c:1032 > #33 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 > #34 0x0051e8fd in gdb_main (args=0x285fee0) at ../../gdb/gdb/main.c:1041 > #35 0x00401737 in main (argc=1, argv=0x293ea0) at ../../gdb/gdb/gdb.c:34 > (gdb) frame 1 > #1 0x00562eb9 in get_pe_section_index (section_name=0x5548638 ".data", > sections=0x4b33b38, nb_sections=5) at ../../gdb/gdb/coff-pe-read.c:113 > 113 if (strcmp (sections[i].section_name, section_name) == 0) > (gdb) p section_name > $1 = 0x5548638 ".data" > (gdb) p i > $2 = 2 > (gdb) p sections[i].section_name > $3 = 0xabababab <Address 0xabababab out of bounds> > (gdb) print *sections@nb_sections > $4 = {{vma_offset = 2089811968, rva_start = 4096, rva_end = 515802, > ms_type = mst_text, section_name = 0x7cd4a0 <coff_sym_fns+64> ".text"}, > { > vma_offset = 2868903936, rva_start = 2880154539, rva_end = 2880154539, > ms_type = mst_unknown, section_name = 0x0}, {vma_offset = 393221, > rva_start = 35784515, rva_end = 1920168494, ms_type = 2880110691, > section_name = 0xabababab <Address 0xabababab out of bounds>}, { > vma_offset = 0, rva_start = 536576, rva_end = 716408, ms_type = > mst_data, > section_name = 0x4b33b68 ".rsrc"}, {vma_offset = 0, rva_start = 716800, > rva_end = 728800, ms_type = mst_data, section_name = 0x4b33be0 > ".reloc"}} > > > > Look, the value "0xabababab", I'm not sure why gdb report: out of bounds, > where does this value come from? 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 ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50c38058.03d0d80a.31dd.4e28SMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50c38058.03d0d80a.31dd.4e28SMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-12-09 2:45 ` asmwarrior 2012-12-09 12:45 ` Pierre Muller [not found] ` <50c487f8.a813b40a.57d7.ffffdc7fSMTPIN_ADDED_BROKEN@mx.google.com> 0 siblings, 2 replies; 59+ messages in thread From: asmwarrior @ 2012-12-09 2:45 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches 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) 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 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 #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. Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-09 2:45 ` asmwarrior @ 2012-12-09 12:45 ` Pierre Muller [not found] ` <50c487f8.a813b40a.57d7.ffffdc7fSMTPIN_ADDED_BROKEN@mx.google.com> 1 sibling, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-09 12:45 UTC (permalink / raw) To: 'asmwarrior' Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches 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 ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50c487f8.a813b40a.57d7.ffffdc7fSMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50c487f8.a813b40a.57d7.ffffdc7fSMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-12-09 13:19 ` asmwarrior 0 siblings, 0 replies; 59+ messages in thread From: asmwarrior @ 2012-12-09 13:19 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches On 2012-12-9 20:45, Pierre Muller wrote: > 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? Sorry, I may be wrong, but look at this post in C::B forum: http://forums.codeblocks.org/index.php/topic,17200.msg117936.html#msg117936 One of the C::B developer said that the debug information is not stripped in the exe/dll files. But whether the codeblocks.exe contains the debug information or not, it did crash gdb when I run the command: file: file d:/software/cb/codeblocks/codeblocks.exe > STOP right here! > > You get a warning about memory corruption before the crash! > So you need to find out why you get this. Here, in my system, I have two codeblocks.exe, one is under my svn_trunk folder(build myself), which cause my gdb crash when I enter "r" command. The other one is from the "codeblocks-12.11-setup.exe", which cause gdb crash when I run the "file xxxxx" command. I'm not sure they refer to the same issue. > 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. It looks like I need to learn some gdb commands I have never used. Do I need to upload myself build codeblocks binaries somewhere that you want try it? Or you can already build codeblocks yourself? Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 7:10 ` Joel Brobecker 2012-12-07 15:23 ` asmwarrior @ 2012-12-13 10:48 ` Pierre Muller [not found] ` <37373.4003318988$1355395714@news.gmane.org> 2 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-13 10:48 UTC (permalink / raw) To: 'Joel Brobecker' Cc: 'asmwarrior', 'Eli Zaretskii', gdb-patches [-- Attachment #1: Type: text/plain, Size: 4543 bytes --] After asmwarrior clarifications that my patch alone didn't cause any crash, I finally committed the patch, after adding the changes suggested by Joel below. The final patch is attached. Concerning Pedro's comments, I will answer to them in his last reply. Thanks to all, Pierre Muller > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Joel Brobecker > Envoyé : vendredi 7 décembre 2012 08:11 > À : Pierre Muller > Cc : 'asmwarrior'; 'Eli Zaretskii'; gdb-patches@sourceware.org > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > > 2012-11-25 Pierre Muller <muller@sourceware.org> > > > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > > * coff-pe-read.c (debug_coff_pe_read): New static variable. > > (struct read_pe_section_data): Add section_name field. > > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. > > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. > > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. > > (get_pe_section_index): New function. > > (struct pe_sections_info): New type. > > (get_section_vmas): Use new struct pe_sections_info. > > (add_pe_exported_sym): Handle unnamed exported function. > > (add_pe_forwarded_sym): New function. > > (read_pe_truncate_name): Truncate at last dot. > > (pe_as16): New function. > > (read_pe_exported_syms): Use ordinal of function to > > retrieve correct RVA address of function and handle > > forwarded symbol. > > (pe_text_section_offset): New function. > > (show_debug_coff_pe_read): New function. > > (_initialize_coff_pe_read): New function adding > > 'set/show debug coff_pe_read' commands. > > > > * windows-tdep.c (windows_xfer_shared_library): Use > > pe_text_section_offset function instead of possibly wrong > > 0x1000 constant for .text sextion offset. > > Looks good - OK to commit after the following minor corrections > have been applied. For the record, I have tested this patch on > x86-windows against AdaCore's GDB testsuite, no regression. > > Thank you! > > > +/* Get the index of the named section in our own full arrayi. > > Small typo at the end if "array". > > > +get_pe_section_index (const char *section_name, > > + struct read_pe_section_data *sections, > > + int nb_sections) > > +{ > > + int i; > > + for (i = 0; i < nb_sections; i++) > > Missing empty line after variable declarations... > > > + DLL_NAME is the internal name of the DLL file, > > + OBJFILE is the objfile struct of DLL_NAME. */ > > + > > + > > +static int > > +add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name, > > Can you delete the second empty line? > > > + char * last_point = strrchr (dll_name, '.'); > > No space between '*' and 'last_point'. > > > + otherix++; > > + section_data = xrealloc (section_data, otherix > > + * sizeof (struct read_pe_section_data)); > > + name = xstrdup (sec_name); > > + section_data[otherix - 1].section_name = name; > > + make_cleanup (xfree, name); > > + section_data[otherix - 1].rva_start = vaddr; > > + section_data[otherix - 1].rva_end = vaddr + vsize; > > + section_data[otherix - 1].vma_offset = 0; > > + if (characteristics & IMAGE_SCN_CNT_CODE) > > + section_data[otherix - 1].ms_type = mst_text; > > + else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) > > + section_data[otherix - 1].ms_type = mst_data; > > + else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) > > + section_data[otherix - 1].ms_type = mst_bss; > > + else > > + section_data[otherix - 1].ms_type = mst_unknown; > > A possible suggestion: It seems simpler to increment otherix > at the end rather than at the beginning, and thus have: > > section_data = xrealloc (section_data, (otherix + 1) [...]); > [...] > section_data[otherix].rva_end = vaddr + vsize; > section_data[otherix].vma_offset = 0; > [...] > otherix++; > > > + /* First handle forward cases. */ > > + if ((func_rva >= export_rva) > > + && (func_rva < export_rva + export_size)) > > You don't need the extra parentheses... > > -- > Joel [-- Attachment #2: fix-dll-offset-v9.patch --] [-- Type: application/octet-stream, Size: 26474 bytes --] 2012-12-13 Pierre Muller <muller@sourceware.org> * coff-pe-read.h (pe_text_section_offset): Declare new function. * coff-pe-read.c (debug_coff_pe_read): New static variable. (struct read_pe_section_data): Add section_name field. (IMAGE_SCN_CNT_CODE): New macro, if not already defined. (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. (get_pe_section_index): New function. (struct pe_sections_info): New type. (get_section_vmas): Use new struct pe_sections_info. (add_pe_exported_sym): Handle unnamed exported function. (add_pe_forwarded_sym): New function. (read_pe_truncate_name): Truncate at last dot. (pe_as16): New function. (read_pe_exported_syms): Use ordinal of function to retrieve correct RVA address of function and handle forwarded symbol. (pe_text_section_offset): New function. (show_debug_coff_pe_read): New function. (_initialize_coff_pe_read): New function adding 'set/show debug coff_pe_read' commands. * windows-tdep.c (windows_xfer_shared_library): Use pe_text_section_offset function instead of possibly wrong 0x1000 constant for .text sextion offset. Index: coff-pe-read.h =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.h,v retrieving revision 1.11 diff -u -p -r1.11 coff-pe-read.h --- coff-pe-read.h 4 Jan 2012 08:17:00 -0000 1.11 +++ coff-pe-read.h 13 Dec 2012 10:41:57 -0000 @@ -23,9 +23,14 @@ #define COFF_PE_READ_H struct objfile; +struct bfd; /* Read the export table and convert it to minimal symbol table entries */ extern void read_pe_exported_syms (struct objfile *objfile); +/* Extract from ABFD the offset of the .text section. + Returns default value 0x1000 if information is not found. */ +extern CORE_ADDR pe_text_section_offset (struct bfd *abfd); + #endif /* !defined (COFF_PE_READ_H) */ Index: coff-pe-read.c =================================================================== RCS file: /cvs/src/src/gdb/coff-pe-read.c,v retrieving revision 1.18 diff -u -p -r1.18 coff-pe-read.c --- coff-pe-read.c 7 Nov 2012 20:10:13 -0000 1.18 +++ coff-pe-read.c 13 Dec 2012 10:41:57 -0000 @@ -28,12 +28,23 @@ #include "bfd.h" #include "gdbtypes.h" +#include "command.h" +#include "gdbcmd.h" #include "symtab.h" #include "symfile.h" #include "objfiles.h" +#include "common/common-utils.h" + +#include <ctype.h> /* Internal section information */ +/* Coff PE read debugging flag: + default value is 0, + value 1 outputs problems encountered while parsing PE file, + value above 1 also lists all generated minimal symbols. */ +static unsigned int debug_coff_pe_read; + struct read_pe_section_data { CORE_ADDR vma_offset; /* Offset to loaded address of section. */ @@ -41,8 +52,18 @@ struct read_pe_section_data unsigned long rva_end; /* End offset within the pe. */ enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */ + char *section_name; /* Recorded section name. */ }; +#ifndef IMAGE_SCN_CNT_CODE +# define IMAGE_SCN_CNT_CODE 0x20 +#endif +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 +#endif +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 +#endif #define PE_SECTION_INDEX_TEXT 0 #define PE_SECTION_INDEX_DATA 1 #define PE_SECTION_INDEX_BSS 2 @@ -77,13 +98,41 @@ read_pe_section_index (const char *secti } } +/* Get the index of the named section in our own full arrayi. + text, data and bss in that order. Return PE_SECTION_INDEX_INVALID + if passed an unrecognised section name. */ + +static int +get_pe_section_index (const char *section_name, + struct read_pe_section_data *sections, + int nb_sections) +{ + int i; + + for (i = 0; i < nb_sections; i++) + if (strcmp (sections[i].section_name, section_name) == 0) + return i; + return PE_SECTION_INDEX_INVALID; +} + +/* Structure used by get_section_vmas function below + to access section_data array and the size of the array + stored in nb_sections field. */ +struct pe_sections_info +{ + int nb_sections; + struct read_pe_section_data *sections; +}; + /* Record the virtual memory address of a section. */ static void get_section_vmas (bfd *abfd, asection *sectp, void *context) { - struct read_pe_section_data *sections = context; - int sectix = read_pe_section_index (sectp->name); + struct pe_sections_info *data = context; + struct read_pe_section_data *sections = data->sections; + int sectix = get_pe_section_index (sectp->name, sections, + data->nb_sections); if (sectix != PE_SECTION_INDEX_INVALID) { @@ -95,58 +144,147 @@ get_section_vmas (bfd *abfd, asection *s } } \f -/* Create a minimal symbol entry for an exported symbol. */ +/* Create a minimal symbol entry for an exported symbol. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FUNC_RVA contains the Relative Virtual Address of the symbol, + ORDINAL is the ordinal index value of the symbol, + SECTION_DATA contains information about the section in which the + symbol is declared, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ static void -add_pe_exported_sym (char *sym_name, +add_pe_exported_sym (const char *sym_name, unsigned long func_rva, + int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile) { + char *qualified_name, *bare_name; /* Add the stored offset to get the loaded address of the symbol. */ - CORE_ADDR vma = func_rva + section_data->vma_offset; - - char *qualified_name = 0; int dll_name_len = strlen (dll_name); /* Generate a (hopefully unique) qualified name using the first part of the dll name, e.g. KERNEL32!AddAtomA. This matches the style used by windbg from the "Microsoft Debugging Tools for Windows". */ - qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2); + if (sym_name == NULL || *sym_name == '\0') + bare_name = xstrprintf ("#%d", ordinal); + else + bare_name = xstrdup (sym_name); + + qualified_name = xstrprintf ("%s!%s", dll_name, bare_name); - strncpy (qualified_name, dll_name, dll_name_len); - qualified_name[dll_name_len] = '!'; - strcpy (qualified_name + dll_name_len + 1, sym_name); + if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\"" + " for entry \"%s\" in dll \"%s\"\n"), + section_data->section_name, sym_name, dll_name); - prim_record_minimal_symbol (qualified_name, - vma, section_data->ms_type, objfile); + prim_record_minimal_symbol (qualified_name, vma, + section_data->ms_type, objfile); + /* Enter the plain name as well, which might not be unique. */ + prim_record_minimal_symbol (bare_name, vma, section_data->ms_type, objfile); + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\"" + " in dll \"%s\"\n"), sym_name, dll_name); xfree (qualified_name); + xfree (bare_name); +} + +/* Create a minimal symbol entry for an exported forward symbol. + Return 1 if the forwarded function was found 0 otherwise. + SYM_NAME contains the exported name or NULL if exported by ordinal, + FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides, + FORWARD_FUNC_NAME is the name of the target symbol in that DLL, + ORDINAL is the ordinal index value of the symbol, + DLL_NAME is the internal name of the DLL file, + OBJFILE is the objfile struct of DLL_NAME. */ + +static int +add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name, + const char *forward_func_name, int ordinal, + const char *dll_name, struct objfile *objfile) +{ + CORE_ADDR vma; + struct objfile *forward_objfile; + struct minimal_symbol *msymbol; + short section; + enum minimal_symbol_type msymtype; + int dll_name_len = strlen (dll_name); + char *qualified_name, *bare_name; + int forward_dll_name_len = strlen (forward_dll_name); + int forward_func_name_len = strlen (forward_func_name); + int forward_len = forward_dll_name_len + forward_func_name_len + 2; + char *forward_qualified_name = alloca (forward_len); + + xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name, + forward_func_name); + + + msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name, + &forward_objfile); + + if (!msymbol) + { + int i; + + for (i = 0; i < forward_dll_name_len; i++) + forward_qualified_name[i] = tolower (forward_qualified_name[i]); + msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name, + &forward_objfile); + } + + if (!msymbol) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in" + " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"), + forward_func_name, forward_dll_name, sym_name, + dll_name); + return 0; + } + + if (debug_coff_pe_read > 1) + fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol" + " \"%s\" in dll \"%s\", pointing to \"%s\"\n"), + sym_name, dll_name, forward_qualified_name); + + vma = SYMBOL_VALUE_ADDRESS (msymbol); + section = SYMBOL_SECTION (msymbol); + msymtype = MSYMBOL_TYPE (msymbol); + + /* Generate a (hopefully unique) qualified name using the first part + of the dll name, e.g. KERNEL32!AddAtomA. This matches the style + used by windbg from the "Microsoft Debugging Tools for Windows". */ + + if (sym_name == NULL || *sym_name == '\0') + bare_name = xstrprintf ("#%d", ordinal); + else + bare_name = xstrdup (sym_name); + + qualified_name = xstrprintf ("%s!%s", dll_name, bare_name); + + prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile); /* Enter the plain name as well, which might not be unique. */ - prim_record_minimal_symbol (sym_name, vma, - section_data->ms_type, objfile); + prim_record_minimal_symbol (bare_name, vma, msymtype, objfile); + xfree (qualified_name); + xfree (bare_name); + + return 1; } -/* Truncate a dll_name at the first dot character. */ +/* Truncate a dll_name at the last dot character. */ static void read_pe_truncate_name (char *dll_name) { - while (*dll_name) - { - if ((*dll_name) == '.') - { - *dll_name = '\0'; /* truncates and causes loop exit. */ - } + char *last_point = strrchr (dll_name, '.'); - else - { - ++dll_name; - } - } + if (last_point != NULL) + *last_point = '\0'; } \f /* Low-level support functions, direct from the ld module pe-dll.c. */ @@ -171,6 +309,14 @@ pe_get32 (bfd *abfd, int where) } static unsigned int +pe_as16 (void *ptr) +{ + unsigned char *b = ptr; + + return b[0] + (b[1] << 8); +} + +static unsigned int pe_as32 (void *ptr) { unsigned char *b = ptr; @@ -186,35 +332,53 @@ void read_pe_exported_syms (struct objfile *objfile) { bfd *dll = objfile->obfd; + unsigned long nbnormal, nbforward; unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_opthdrrva, export_opthdrsize; unsigned long export_rva, export_size, nsections, secptr, expptr; unsigned long exp_funcbase; unsigned char *expdata, *erva; unsigned long name_rvas, ordinals, nexp, ordbase; - char *dll_name; + char *dll_name = (char *) dll->filename; + int otherix = PE_SECTION_TABLE_SIZE; + int exportix = -1; int is_pe64 = 0; int is_pe32 = 0; /* Array elements are for text, data and bss in that order - Initialization with start_rva > end_rva guarantees that + Initialization with RVA_START > RVA_END guarantees that unused sections won't be matched. */ - struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE] - = { {0, 1, 0, mst_text}, - {0, 1, 0, mst_data}, - {0, 1, 0, mst_bss} - }; + struct read_pe_section_data *section_data; + struct pe_sections_info pe_sections_info; - struct cleanup *back_to = 0; + struct cleanup *back_to = make_cleanup (null_cleanup, 0); char const *target = bfd_get_target (objfile->obfd); + section_data = xzalloc (PE_SECTION_TABLE_SIZE + * sizeof (struct read_pe_section_data)); + + make_cleanup (free_current_contents, §ion_data); + + for (i=0; i < PE_SECTION_TABLE_SIZE; i++) + { + section_data[i].vma_offset = 0; + section_data[i].rva_start = 1; + section_data[i].rva_end = 0; + }; + section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text; + section_data[PE_SECTION_INDEX_TEXT].section_name = ".text"; + section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data; + section_data[PE_SECTION_INDEX_DATA].section_name = ".data"; + section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss; + section_data[PE_SECTION_INDEX_BSS].section_name = ".bss"; + is_pe64 = (strcmp (target, "pe-x86-64") == 0 || strcmp (target, "pei-x86-64") == 0); is_pe32 = (strcmp (target, "pe-i386") == 0 || strcmp (target, "pei-i386") == 0 || strcmp (target, "pe-arm-wince-little") == 0 || strcmp (target, "pei-arm-wince-little") == 0); - if (!is_pe32 && !is_pe64) { /* This is not a recognized PE format file. Abort now, because @@ -235,21 +399,21 @@ read_pe_exported_syms (struct objfile *o { return; } - if (is_pe64) { - export_rva = pe_get32 (dll, opthdr_ofs + 112); - export_size = pe_get32 (dll, opthdr_ofs + 116); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116); } else { - export_rva = pe_get32 (dll, opthdr_ofs + 96); - export_size = pe_get32 (dll, opthdr_ofs + 100); + export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96); + export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100); } nsections = pe_get16 (dll, pe_header_offset + 4 + 2); secptr = (pe_header_offset + 4 + 20 + pe_get16 (dll, pe_header_offset + 4 + 16)); expptr = 0; + export_size = 0; /* Get the rva and size of the export section. */ for (i = 0; i < nsections; i++) @@ -261,17 +425,31 @@ read_pe_exported_syms (struct objfile *o unsigned long fptr = pe_get32 (dll, secptr1 + 20); bfd_seek (dll, (file_ptr) secptr1, SEEK_SET); - bfd_bread (sname, (bfd_size_type) 8, dll); + bfd_bread (sname, (bfd_size_type) sizeof (sname), dll); - if (vaddr <= export_rva && vaddr + vsize > export_rva) + if ((strcmp (sname, ".edata") == 0) + || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize)) { - expptr = fptr + (export_rva - vaddr); - if (export_rva + export_size > vaddr + vsize) - export_size = vsize - (export_rva - vaddr); + if (strcmp (sname, ".edata") != 0) + { + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll " + "\"%s\" is in section \"%s\"\n"), + dll_name, sname); + } + else if (export_opthdrrva != vaddr && debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA" + " for dll \"%s\": 0x%lx instead of 0x%lx\n"), + dll_name, export_opthdrrva, vaddr); + expptr = fptr + (export_opthdrrva - vaddr); + exportix = i; break; } } + export_rva = export_opthdrrva; + export_size = export_opthdrsize; + if (export_size == 0) { /* Empty export table. */ @@ -285,10 +463,11 @@ read_pe_exported_syms (struct objfile *o unsigned long secptr1 = secptr + 40 * i; unsigned long vsize = pe_get32 (dll, secptr1 + 8); unsigned long vaddr = pe_get32 (dll, secptr1 + 12); + unsigned long characteristics = pe_get32 (dll, secptr1 + 36); char sec_name[9]; int sectix; - sec_name[8] = '\0'; + memset (sec_name, 0, sizeof (sec_name)); bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET); bfd_bread (sec_name, (bfd_size_type) 8, dll); @@ -299,10 +478,32 @@ read_pe_exported_syms (struct objfile *o section_data[sectix].rva_start = vaddr; section_data[sectix].rva_end = vaddr + vsize; } + 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); + 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++; + } } expdata = (unsigned char *) xmalloc (export_size); - back_to = make_cleanup (xfree, expdata); + make_cleanup (xfree, expdata); bfd_seek (dll, (file_ptr) expptr, SEEK_SET); bfd_bread (expdata, (bfd_size_type) export_size, dll); @@ -317,12 +518,15 @@ read_pe_exported_syms (struct objfile *o /* Use internal dll name instead of full pathname. */ dll_name = pe_as32 (expdata + 12) + erva; - bfd_map_over_sections (dll, get_section_vmas, section_data); + pe_sections_info.nb_sections = otherix; + pe_sections_info.sections = section_data; + + bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info); /* Adjust the vma_offsets in case this PE got relocated. This assumes that *all* sections share the same relocation offset as the text section. */ - for (i = 0; i < PE_SECTION_TABLE_SIZE; i++) + for (i = 0; i < otherix; i++) { section_data[i].vma_offset += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -332,31 +536,184 @@ read_pe_exported_syms (struct objfile *o lower case for convenience on Windows. */ read_pe_truncate_name (dll_name); + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries," + " base=%ld\n"), dll_name, nexp, ordbase); + nbforward = 0; + nbnormal = 0; /* Iterate through the list of symbols. */ for (i = 0; i < nexp; i++) { /* Pointer to the names vector. */ unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4); + /* Retrieve ordinal value. */ + + unsigned long ordinal = pe_as16 (erva + ordinals + i * 2); + /* Pointer to the function address vector. */ - unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4); + /* This is relatived to ordinal value. */ + unsigned long func_rva = pe_as32 (erva + exp_funcbase + + ordinal * 4); /* Find this symbol's section in our own array. */ int sectix = 0; + int section_found = 0; + + /* First handle forward cases. */ + if (func_rva >= export_rva && func_rva < export_rva + export_size) + { + char *forward_name = (char *) (erva + func_rva); + char *funcname = (char *) (erva + name_rva); + char *forward_dll_name = forward_name; + char *forward_func_name = forward_name; + char *sep = strrchr (forward_name, '.'); + + if (sep) + { + int len = (int) (sep - forward_name); - for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix) + forward_dll_name = alloca (len + 1); + strncpy (forward_dll_name, forward_name, len); + forward_dll_name[len] = '\0'; + forward_func_name = ++sep; + } + if (add_pe_forwarded_sym (funcname, forward_dll_name, + forward_func_name, ordinal, + dll_name, objfile) != 0) + ++nbforward; + continue; + } + + for (sectix = 0; sectix < otherix; ++sectix) { if ((func_rva >= section_data[sectix].rva_start) && (func_rva < section_data[sectix].rva_end)) { + section_found = 1; add_pe_exported_sym (erva + name_rva, - func_rva, + func_rva, ordinal, section_data + sectix, dll_name, objfile); + ++nbnormal; break; } } + if (!section_found) + { + char *funcname = (char *) (erva + name_rva); + + if (name_rva == 0) + { + add_pe_exported_sym (NULL, func_rva, ordinal, + section_data, dll_name, objfile); + ++nbnormal; + } + else if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu," + " RVA 0x%lx in dll \"%s\" not handled\n"), + funcname, ordinal, func_rva, dll_name); + } } - /* Discard expdata. */ + if (debug_coff_pe_read) + fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld," + " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal, + nbforward, nbnormal + nbforward, nexp); + /* Discard expdata and section_data. */ do_cleanups (back_to); } + +/* Extract from ABFD the offset of the .text section. + This offset is mainly related to the offset within the file. + The value was previously expected to be 0x1000 for all files, + but some Windows OS core DLLs seem to use 0x10000 section alignement + which modified the return value of that function. + Still return default 0x1000 value if ABFD is NULL or + if '.text' section is not found, but that should not happen... */ + +#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000 + +CORE_ADDR +pe_text_section_offset (struct bfd *abfd) + +{ + unsigned long pe_header_offset, opthdr_ofs, num_entries, i; + unsigned long export_rva, export_size, nsections, secptr, expptr; + unsigned long exp_funcbase; + unsigned char *expdata, *erva; + unsigned long name_rvas, ordinals, nexp, ordbase; + char *dll_name; + int is_pe64 = 0; + int is_pe32 = 0; + char const *target; + + if (!abfd) + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + + target = bfd_get_target (abfd); + + is_pe64 = (strcmp (target, "pe-x86-64") == 0 + || strcmp (target, "pei-x86-64") == 0); + is_pe32 = (strcmp (target, "pe-i386") == 0 + || strcmp (target, "pei-i386") == 0 + || strcmp (target, "pe-arm-wince-little") == 0 + || strcmp (target, "pei-arm-wince-little") == 0); + + if (!is_pe32 && !is_pe64) + { + /* This is not a recognized PE format file. Abort now, because + the code is untested on anything else. *FIXME* test on + further architectures and loosen or remove this test. */ + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; + } + + /* Get pe_header, optional header and numbers of sections. */ + pe_header_offset = pe_get32 (abfd, 0x3c); + opthdr_ofs = pe_header_offset + 4 + 20; + nsections = pe_get16 (abfd, pe_header_offset + 4 + 2); + secptr = (pe_header_offset + 4 + 20 + + pe_get16 (abfd, pe_header_offset + 4 + 16)); + + /* Get the rva and size of the export section. */ + for (i = 0; i < nsections; i++) + { + char sname[8]; + unsigned long secptr1 = secptr + 40 * i; + unsigned long vaddr = pe_get32 (abfd, secptr1 + 12); + + bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET); + bfd_bread (sname, (bfd_size_type) 8, abfd); + if (strcmp (sname, ".text") == 0) + return vaddr; + } + + return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET; +} + +/* Implements "show debug coff_pe_read" command. */ + +static void +show_debug_coff_pe_read (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ + +void _initialize_coff_pe_read (void); + +/* Adds "Set/show debug coff_pe_read" commands. */ + +void +_initialize_coff_pe_read (void) +{ + add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance, + &debug_coff_pe_read, + _("Set coff PE read debugging."), + _("Show coff PE read debugging."), + _("When set, debugging messages for coff reading " + "of exported symbols are displayed."), + NULL, show_debug_coff_pe_read, + &setdebuglist, &showdebuglist); +} Index: windows-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/windows-tdep.c,v retrieving revision 1.17 diff -u -p -r1.17 windows-tdep.c --- windows-tdep.c 9 Nov 2012 19:58:02 -0000 1.17 +++ windows-tdep.c 13 Dec 2012 10:41:57 -0000 @@ -27,6 +27,10 @@ #include "gdbcmd.h" #include "gdbthread.h" #include "objfiles.h" +#include "symfile.h" +#include "coff-pe-read.h" +#include "gdb_bfd.h" +#include "complaints.h" struct cmd_list_element *info_w32_cmdlist; @@ -387,15 +391,21 @@ windows_xfer_shared_library (const char* struct gdbarch *gdbarch, struct obstack *obstack) { char *p; + struct bfd * dll; + CORE_ADDR text_offset; + obstack_grow_str (obstack, "<library name=\""); p = xml_escape_text (so_name); obstack_grow_str (obstack, p); xfree (p); obstack_grow_str (obstack, "\"><segment address=\""); - /* The symbols in a dll are offset by 0x1000, which is the - offset from 0 of the first byte in an image - because of the file - header and the section alignment. */ - obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000)); + dll = gdb_bfd_open_maybe_remote (so_name); + /* The following calls are OK even if dll is NULL. + The default value 0x1000 is returned by pe_text_section_offset + in that case. */ + text_offset = pe_text_section_offset (dll); + gdb_bfd_unref (dll); + obstack_grow_str (obstack, paddress (gdbarch, load_addr + text_offset)); obstack_grow_str (obstack, "\"/></library>"); } ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <37373.4003318988$1355395714@news.gmane.org>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <37373.4003318988$1355395714@news.gmane.org> @ 2012-12-13 16:16 ` Tom Tromey 2012-12-13 16:21 ` Pierre Muller [not found] ` <12936.6976012991$1355415704@news.gmane.org> 0 siblings, 2 replies; 59+ messages in thread From: Tom Tromey @ 2012-12-13 16:16 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'asmwarrior', 'Eli Zaretskii', gdb-patches >>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes: Pierre> struct read_pe_section_data Pierre> { Pierre> CORE_ADDR vma_offset; /* Offset to loaded address of section. */ Pierre> @@ -41,8 +52,18 @@ struct read_pe_section_data Pierre> unsigned long rva_end; /* End offset within the pe. */ Pierre> enum minimal_symbol_type ms_type; /* Type to assign symbols in Pierre> section. */ Pierre> + char *section_name; /* Recorded section name. */ It seems like this could be const. Tom ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-13 16:16 ` Tom Tromey @ 2012-12-13 16:21 ` Pierre Muller [not found] ` <12936.6976012991$1355415704@news.gmane.org> 1 sibling, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-12-13 16:21 UTC (permalink / raw) To: 'Tom Tromey' Cc: 'Joel Brobecker', 'asmwarrior', 'Eli Zaretskii', gdb-patches > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Tom Tromey > Envoyé : jeudi 13 décembre 2012 17:16 > À : Pierre Muller > Cc : 'Joel Brobecker'; 'asmwarrior'; 'Eli Zaretskii'; gdb- > patches@sourceware.org > Objet : Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > >>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes: > > Pierre> struct read_pe_section_data > Pierre> { > Pierre> CORE_ADDR vma_offset; /* Offset to loaded address of > section. */ > Pierre> @@ -41,8 +52,18 @@ struct read_pe_section_data > Pierre> unsigned long rva_end; /* End offset within the pe. */ > Pierre> enum minimal_symbol_type ms_type; /* Type to assign symbols in > Pierre> section. */ > Pierre> + char *section_name; /* Recorded section name. */ > > It seems like this could be const. Sorry, but you will need to teach me some more C language so that I understand what that would change... In pascal the const only exists for function/procedure parameters not for fields of structures... Does it simply mean that any attempt to use it as a (char *) type will result in an error? But them, how can you set the value of such a field? Sorry about my ignorance... Remember that I am a pascal fan lost in C land just because I maintain GDB pascal language support... Pierre ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <12936.6976012991$1355415704@news.gmane.org>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <12936.6976012991$1355415704@news.gmane.org> @ 2012-12-13 20:05 ` Tom Tromey 0 siblings, 0 replies; 59+ messages in thread From: Tom Tromey @ 2012-12-13 20:05 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'asmwarrior', 'Eli Zaretskii', gdb-patches Pierre> + char *section_name; /* Recorded section name. Tom> It seems like this could be const. Pierre> Sorry, Pierre> but you will need to teach me some more C language Pierre> so that I understand what that would change... Pierre> In pascal the const only exists for function/procedure parameters Pierre> not for fields of structures... Pierre> Does it simply mean that any attempt to use it Pierre> as a (char *) type will result in an error? Pierre> But them, how can you set the value of such a field? In C the const modifies the type. So "const char *section_name" means "section name is a pointer to const characters" -- that is, the characters cannot be modified via the "section_name" pointer. In this case const is probably borderline useful. In other parts of gdb, where used[*], it serves both a documentation purpose and as a barrier against coding mistakes. [*] It isn't extremely widely used since gdb predates the existence of const. Pierre> Sorry about my ignorance... Pierre> Remember that I am a pascal fan lost in C land just because Pierre> I maintain GDB pascal language support... No worries. Tom ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <42721.1671988063$1354028360@news.gmane.org>]
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <42721.1671988063$1354028360@news.gmane.org> @ 2012-11-28 2:44 ` asmwarrior 2012-11-29 3:40 ` asmwarrior 2012-12-12 0:59 ` asmwarrior 1 sibling, 1 reply; 59+ messages in thread From: asmwarrior @ 2012-11-28 2:44 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches On 2012-11-27 22:58, Pierre Muller wrote: > Thanks, Tom... > it really seems that this is the culprit: > I was freeing again already freed memory, which of course > created random crashes later. > > I send here rapidly a new patch version. > I really tested the allocation problems by adding > allocation + free'ing of each of the first parameters > used in prim_record_minimal_symbol > and it does seem that freeing of char array doesn't lead to any problem. > > So the only trouble was related to the > reallocation of section_data and seems to be fixed > thanks to Tom's proposal. > > Yuanhui Zhang, > could you please check if the new patch > suppresses the crash you had when you tried the previous version? > > Thanks to everyone... > > Pierre Muller > I just tested this new patch, and the crash issue is gone. Thanks. Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-28 2:44 ` asmwarrior @ 2012-11-29 3:40 ` asmwarrior 0 siblings, 0 replies; 59+ messages in thread From: asmwarrior @ 2012-11-29 3:40 UTC (permalink / raw) To: gdb-patches On 2012-11-28 10:46, asmwarrior wrote: > I just tested this new patch, and the crash issue is gone. Thanks. Sorry, I still see the crash issue when I try to debug/load a large app(Codeblocks.exe, which depends a lot of dlls) GDB without your patch does not crash. So, I suspect there is still some memory leaks(allocate/free issue). Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v5] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <42721.1671988063$1354028360@news.gmane.org> 2012-11-28 2:44 ` asmwarrior @ 2012-12-12 0:59 ` asmwarrior 1 sibling, 0 replies; 59+ messages in thread From: asmwarrior @ 2012-12-12 0:59 UTC (permalink / raw) To: Pierre Muller Cc: 'Tom Tromey', 'Joel Brobecker', 'Pedro Alves', 'Eli Zaretskii', gdb-patches On 2012-11-27 22:58, Pierre Muller wrote: > Thanks, Tom... > it really seems that this is the culprit: > I was freeing again already freed memory, which of course > created random crashes later. > > I send here rapidly a new patch version. > I really tested the allocation problems by adding > allocation + free'ing of each of the first parameters > used in prim_record_minimal_symbol > and it does seem that freeing of char array doesn't lead to any problem. > > So the only trouble was related to the > reallocation of section_data and seems to be fixed > thanks to Tom's proposal. > > Yuanhui Zhang, > could you please check if the new patch > suppresses the crash you had when you tried the previous version? > > Thanks to everyone... > > Pierre Muller > > > 2012-11-25 Pierre Muller <muller@sourceware.org> > > * coff-pe-read.h (pe_text_section_offset): Declare new function. > * coff-pe-read.c (debug_coff_pe_read): New static variable. > (struct read_pe_section_data): Add section_name field. > (IMAGE_SCN_CNT_CODE): New macro, if not already defined. > (IMAGE_SCN_CNT_INITIALIZED_DATA): Ditto. > (IMAGE_SCN_CNT_UNINITIALIZED_DATA): Ditto. > (get_pe_section_index): New function. > (struct pe_sections_info): New type. > (get_section_vmas): Use new struct pe_sections_info. > (add_pe_exported_sym): Handle unnamed exported function. > (add_pe_forwarded_sym): New function. > (read_pe_truncate_name): Truncate at last dot. > (pe_as16): New function. > (read_pe_exported_syms): Use ordinal of function to > retrieve correct RVA address of function and handle > forwarded symbol. > (pe_text_section_offset): New function. > (show_debug_coff_pe_read): New function. > (_initialize_coff_pe_read): New function adding > 'set/show debug coff_pe_read' commands. > > * windows-tdep.c (windows_xfer_shared_library): Use > pe_text_section_offset function instead of possibly wrong > 0x1000 constant for .text sextion offset. > I test this patch again, it works fine without crash in the below cases: gdb_pure_cvs_20121207 + this patch + python_enabled ----> No crash on debugging, "print GetLastError()" works correctly. gdb_pure_cvs_20121207 + this patch + python_disabled----> No crash on debugging, "print GetLastError()" works correctly. Yuanhui Zhang ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <50b2a0d1.c849420a.3a3a.3538SMTPIN_ADDED_BROKEN@mx.google.com>]
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <50b2a0d1.c849420a.3a3a.3538SMTPIN_ADDED_BROKEN@mx.google.com> @ 2012-12-07 16:38 ` Pedro Alves 2012-12-07 17:03 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Pedro Alves @ 2012-12-07 16:38 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches On 11/25/2012 10:50 PM, Pierre Muller wrote: >>> > > +#ifndef IMAGE_SCN_CNT_CODE >>> > > +# define IMAGE_SCN_CNT_CODE 0x20 >>> > > +#endif >>> > > +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA >>> > > +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 >>> > > +#endif >>> > > +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA >>> > > +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 >>> > > +#endif >> > Do you have an idea of when these macros might not be defined? >> > (and where they are normally coming from?). It'd be nice to add >> > a comment providing the answer to those questions. > > These are windows specific macros, > but can also be compiled on any other target, if one > of the windows target is included in the target list. But then, when _are_ they defined? You mean they're being picked up by something including windows.h on Windows hosts? It'd be much better if they were defined in src/include/coff/pe.h, like other IMAGE_SCN_ constants. -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 16:38 ` [RFC-v4] " Pedro Alves @ 2012-12-07 17:03 ` Pierre Muller 2012-12-07 17:50 ` Pedro Alves 0 siblings, 1 reply; 59+ messages in thread From: Pierre Muller @ 2012-12-07 17:03 UTC (permalink / raw) To: 'Pedro Alves' Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches Hi Pedro, The values are indeed included in include/coff/pe.h header... The problem is that coff-pe-read.c was written completely without the use of this header. Using that header would probably be better, but would also require even more rewrite of current code... I tried nevertheless to include coff/pe.h I got an error about AOUTHDR not being defined, which requires adding coff/external.h but if I add that one, I get another error that L_LNNO_SIZE must be defined... And that one is defined in cpu specific files coff/CPU.h This seems to mean that including pe.h is not that easy :( Pierre > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Pedro Alves > Envoyé : vendredi 7 décembre 2012 17:38 > À : Pierre Muller > Cc : 'Joel Brobecker'; 'Eli Zaretskii'; gdb-patches@sourceware.org > Objet : Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > On 11/25/2012 10:50 PM, Pierre Muller wrote: > >>> > > +#ifndef IMAGE_SCN_CNT_CODE > >>> > > +# define IMAGE_SCN_CNT_CODE 0x20 > >>> > > +#endif > >>> > > +#ifndef IMAGE_SCN_CNT_INITIALIZED_DATA > >>> > > +# define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40 > >>> > > +#endif > >>> > > +#ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA > >>> > > +# define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80 > >>> > > +#endif > >> > Do you have an idea of when these macros might not be defined? > >> > (and where they are normally coming from?). It'd be nice to add > >> > a comment providing the answer to those questions. > > > > These are windows specific macros, > > but can also be compiled on any other target, if one > > of the windows target is included in the target list. > > But then, when _are_ they defined? You mean they're being picked > up by something including windows.h on Windows hosts? > It'd be much better if they were defined in src/include/coff/pe.h, > like other IMAGE_SCN_ constants. > > -- > Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC-v4] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-12-07 17:03 ` Pierre Muller @ 2012-12-07 17:50 ` Pedro Alves 0 siblings, 0 replies; 59+ messages in thread From: Pedro Alves @ 2012-12-07 17:50 UTC (permalink / raw) To: Pierre Muller Cc: 'Joel Brobecker', 'Eli Zaretskii', gdb-patches Please don't top post. On 12/07/2012 05:03 PM, Pierre Muller wrote: > Hi Pedro, > > The values are indeed included in include/coff/pe.h header... > The problem is that coff-pe-read.c was > written completely without the use of this > header. > Using that header would probably be better, > but would also require even more rewrite > of current code... > > I tried nevertheless to include coff/pe.h > I got an error about AOUTHDR not being defined, > which requires adding coff/external.h > but if I add that one, I get another error > that L_LNNO_SIZE must be defined... > And that one is defined in cpu specific files > coff/CPU.h > > This seems to mean that including pe.h is not that easy :( Yuck. It'd be nice if the architecture independent bits of pe.h were split into a separate file, e.g., pe-common.h. But I'll agree that this should not be a requirement for this patch. But I'm still confused on why do you need "#ifndef IMAGE_SCN_CNT_CODE" instead of unconditionally defining the constants. What is pulling a header that defines these? -- Pedro Alves ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <000301cdbd96$f5cd9f10$e168dd30$%muller@ics-cnrs.unistra.fr>]
* Re: [RFC-v3] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <000301cdbd96$f5cd9f10$e168dd30$%muller@ics-cnrs.unistra.fr> @ 2012-11-17 10:01 ` Eli Zaretskii 0 siblings, 0 replies; 59+ messages in thread From: Eli Zaretskii @ 2012-11-17 10:01 UTC (permalink / raw) To: Pierre Muller; +Cc: palves, brobecker, gdb-patches > From: "Pierre Muller" <pierre.muller@ics-cnrs.unistra.fr> > Cc: "'Joel Brobecker'" <brobecker@adacore.com>, <gdb-patches@sourceware.org> > Date: Thu, 8 Nov 2012 10:53:42 +0100 > > This is an adapted patch after the change by Pedro > to always place defs.h as first include header. > > This is just for convenience as the previous patch probably would create > conflicts if applied to up-to-date CVS tree. > > For Eli, I also attached a second version > called fix-dll-branch.patch > that applies to gdb_7_5-branch. Thanks, I tested the patch for the branch, and it solves my problem with calling GetLastError. I'd love to see this patch in a future version of GDB. ^ permalink raw reply [flat|nested] 59+ messages in thread
[parent not found: <006001cdaada$00c81f00$02585d00$%muller@ics-cnrs.unistra.fr>]
* Re: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) [not found] ` <006001cdaada$00c81f00$02585d00$%muller@ics-cnrs.unistra.fr> @ 2012-10-15 17:23 ` Eli Zaretskii 2012-11-03 10:36 ` Eli Zaretskii 0 siblings, 1 reply; 59+ messages in thread From: Eli Zaretskii @ 2012-10-15 17:23 UTC (permalink / raw) To: Pierre Muller; +Cc: gdb-patches > From: "Pierre Muller" <pierre.muller@ics-cnrs.unistra.fr> > Date: Mon, 15 Oct 2012 15:35:55 +0200 > > After some investigation, I noticed that > the minimal symbol GetLastError was offset by 0xf0000 > respective to the '_imp__GetLastError@0'. > > The patch attached allowed me to call > (gdb) call GetLastError () > And get a simple > $2 = 126 > (for instance, depending on when you do the call). Thanks. > Could someone please test the patch and > confirm that it does fix the problem? I will try that in a few days. > + if (!section_found) > + { > + char * forward_name = (char *) (erva + func_rva); > + char * funcname = (char *) (erva + name_rva); > + if ((func_rva >= export_rva) > + && (func_rva < export_rva + export_size)) > + printf ("%s is a forward to %s\n", funcname, forward_name); Is this printf really necessary? ^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-10-15 17:23 ` [RFC] " Eli Zaretskii @ 2012-11-03 10:36 ` Eli Zaretskii 2012-11-06 13:55 ` Pierre Muller 0 siblings, 1 reply; 59+ messages in thread From: Eli Zaretskii @ 2012-11-03 10:36 UTC (permalink / raw) To: pierre.muller; +Cc: gdb-patches > Date: Mon, 15 Oct 2012 19:23:13 +0200 > From: Eli Zaretskii <eliz@gnu.org> > Cc: gdb-patches@sourceware.org > > > From: "Pierre Muller" <pierre.muller@ics-cnrs.unistra.fr> > > Date: Mon, 15 Oct 2012 15:35:55 +0200 > > > > After some investigation, I noticed that > > the minimal symbol GetLastError was offset by 0xf0000 > > respective to the '_imp__GetLastError@0'. > > > > The patch attached allowed me to call > > (gdb) call GetLastError () > > And get a simple > > $2 = 126 > > (for instance, depending on when you do the call). > > Thanks. > > > Could someone please test the patch and > > confirm that it does fix the problem? > > I will try that in a few days. Sorry for the long delay. I tried that now, but then I realized that the patch cannot be applied to GDB 7.5, because it uses gdb_bfd.h stuff. I tried to work around that by replacing the call to gdb_bfd_open_maybe_remote by bfd_open_maybe_remote; that compiled, but when I tried to use the resulting binary, it crashed in the marked assertion: gdb.exe caused an Access Violation at location 00532b99 in module gdb.exe Reading from location 00000000. 00532B99 gdb.exe:00532B99 gdb_bfd_unref objfiles.c:1514 ... /* Valid range for p_refcount: a pointer to int counter, which has a value of 1 (single owner) or 2 (shared). */ > gdb_assert (*p_refcount == 1 || *p_refcount == 2); *p_refcount -= 1; ... Is it possible to have a patch for GDB 7.5? TIA ^ permalink raw reply [flat|nested] 59+ messages in thread
* RE: [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) 2012-11-03 10:36 ` Eli Zaretskii @ 2012-11-06 13:55 ` Pierre Muller 0 siblings, 0 replies; 59+ messages in thread From: Pierre Muller @ 2012-11-06 13:55 UTC (permalink / raw) To: 'Eli Zaretskii'; +Cc: gdb-patches > -----Message d'origine----- > De : gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] De la part de Eli Zaretskii > Envoyé : samedi 3 novembre 2012 11:36 > À : pierre.muller@ics-cnrs.unistra.fr > Cc : gdb-patches@sourceware.org > Objet : Re: [RFC] Fix .text section offset for windows DLL (was Calling > __stdcall functions in the inferior) > > > Date: Mon, 15 Oct 2012 19:23:13 +0200 > > From: Eli Zaretskii <eliz@gnu.org> > > Cc: gdb-patches@sourceware.org > > > > > From: "Pierre Muller" <pierre.muller@ics-cnrs.unistra.fr> > > > Date: Mon, 15 Oct 2012 15:35:55 +0200 > > > > > > After some investigation, I noticed that > > > the minimal symbol GetLastError was offset by 0xf0000 > > > respective to the '_imp__GetLastError@0'. > > > > > > The patch attached allowed me to call > > > (gdb) call GetLastError () > > > And get a simple > > > $2 = 126 > > > (for instance, depending on when you do the call). > > > > Thanks. > > > > > Could someone please test the patch and > > > confirm that it does fix the problem? > > > > I will try that in a few days. > > Sorry for the long delay. > > I tried that now, but then I realized that the patch cannot be applied > to GDB 7.5, because it uses gdb_bfd.h stuff. I tried to work around > that by replacing the call to gdb_bfd_open_maybe_remote by > bfd_open_maybe_remote; that compiled, but when I tried to use the > resulting binary, it crashed in the marked assertion: Just try to completely remove the call to gdb_bfd_unref and it should work fine (at least to try it out, because it will probably leak some file handles that way...) I will resubmit another patch version shortly and the same change should also allow it to be applied to 7.5 version. Pierre Muller ^ permalink raw reply [flat|nested] 59+ messages in thread
end of thread, other threads:[~2012-12-13 20:05 UTC | newest] Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <83a9vs89r9.fsf@gnu.org> [not found] ` <201210120953.q9C9rqfu020865@glazunov.sibelius.xs4all.nl> [not found] ` <834nm07z0s.fsf@gnu.org> [not found] ` <5077FEB9.4030304@redhat.com> [not found] ` <83y5jb7rfe.fsf@gnu.org> 2012-10-15 13:36 ` [RFC] Fix .text section offset for windows DLL (was Calling __stdcall functions in the inferior) Pierre Muller 2012-10-24 19:45 ` Joel Brobecker 2012-10-25 12:21 ` Pierre Muller 2012-11-05 17:11 ` Joel Brobecker 2012-11-06 14:31 ` [RFC-v2] " Pierre Muller [not found] ` <50991f5f.8382440a.1100.ffff82abSMTPIN_ADDED@mx.google.com> 2012-11-07 19:44 ` Pedro Alves 2012-11-08 9:54 ` [RFC-v3] " Pierre Muller 2012-11-22 17:30 ` Joel Brobecker 2012-11-22 17:51 ` Pedro Alves 2012-11-25 22:50 ` [RFC-v4] " Pierre Muller 2012-11-26 17:22 ` Joel Brobecker 2012-11-26 18:36 ` Tom Tromey 2012-11-26 20:58 ` Joel Brobecker [not found] ` <15690.5992342674$1353883881@news.gmane.org> 2012-11-26 4:04 ` asmwarrior 2012-11-26 10:14 ` Pierre Muller [not found] ` <50b340fb.0aec440a.1c48.5818SMTPIN_ADDED_BROKEN@mx.google.com> 2012-11-26 11:39 ` Pedro Alves 2012-11-26 16:54 ` Tom Tromey 2012-11-27 14:59 ` [RFC-v5] " Pierre Muller 2012-12-07 7:10 ` Joel Brobecker 2012-12-07 15:23 ` asmwarrior 2012-12-07 15:41 ` Pierre Muller [not found] ` <29545.4593528577$1354894901@news.gmane.org> 2012-12-07 16:15 ` asmwarrior 2012-12-07 16:27 ` Pierre Muller [not found] ` <50c21914.a750420a.2ec3.ffffe4ffSMTPIN_ADDED_BROKEN@mx.google.com> 2012-12-07 17:10 ` Pedro Alves 2012-12-07 17:49 ` Pedro Alves 2012-12-13 10:57 ` Pierre Muller 2012-12-13 11:07 ` Pedro Alves 2012-12-13 11:49 ` Pedro Alves [not found] ` <00a201cdd931$b0ee13f0$12ca3bd0$@muller@ics-cnrs.unistra.fr> 2012-12-13 14:32 ` Pedro Alves 2012-12-13 15:17 ` Pierre Muller 2012-12-13 14:33 ` Pedro Alves 2012-12-13 14:56 ` Pierre Muller 2012-12-13 15:03 ` Pedro Alves 2012-12-13 16:43 ` Pedro Alves 2012-12-13 16:54 ` Pierre Muller 2012-12-13 16:56 ` Pedro Alves 2012-12-13 17:09 ` Pierre Muller 2012-12-13 15:08 ` Pierre Muller 2012-12-13 16:04 ` Pedro Alves [not found] ` <50c218e5.2850b40a.0281.ffffbef4SMTPIN_ADDED_BROKEN@mx.google.com> 2012-12-08 14:17 ` asmwarrior 2012-12-08 15:07 ` asmwarrior 2012-12-08 18:01 ` Pierre Muller [not found] ` <50c38058.03d0d80a.31dd.4e28SMTPIN_ADDED_BROKEN@mx.google.com> 2012-12-09 2:45 ` asmwarrior 2012-12-09 12:45 ` Pierre Muller [not found] ` <50c487f8.a813b40a.57d7.ffffdc7fSMTPIN_ADDED_BROKEN@mx.google.com> 2012-12-09 13:19 ` asmwarrior 2012-12-13 10:48 ` Pierre Muller [not found] ` <37373.4003318988$1355395714@news.gmane.org> 2012-12-13 16:16 ` Tom Tromey 2012-12-13 16:21 ` Pierre Muller [not found] ` <12936.6976012991$1355415704@news.gmane.org> 2012-12-13 20:05 ` Tom Tromey [not found] ` <42721.1671988063$1354028360@news.gmane.org> 2012-11-28 2:44 ` asmwarrior 2012-11-29 3:40 ` asmwarrior 2012-12-12 0:59 ` asmwarrior [not found] ` <50b2a0d1.c849420a.3a3a.3538SMTPIN_ADDED_BROKEN@mx.google.com> 2012-12-07 16:38 ` [RFC-v4] " Pedro Alves 2012-12-07 17:03 ` Pierre Muller 2012-12-07 17:50 ` Pedro Alves [not found] ` <000301cdbd96$f5cd9f10$e168dd30$%muller@ics-cnrs.unistra.fr> 2012-11-17 10:01 ` [RFC-v3] " Eli Zaretskii [not found] ` <006001cdaada$00c81f00$02585d00$%muller@ics-cnrs.unistra.fr> 2012-10-15 17:23 ` [RFC] " Eli Zaretskii 2012-11-03 10:36 ` Eli Zaretskii 2012-11-06 13:55 ` Pierre Muller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).