From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3615 invoked by alias); 24 Jun 2013 03:11:58 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 3596 invoked by uid 89); 24 Jun 2013 03:11:57 -0000 X-Spam-SWARE-Status: No, score=-3.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,KHOP_RCVD_UNTRUST,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_BJ,TW_BM,TW_YM autolearn=no version=3.3.1 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 24 Jun 2013 03:11:56 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1UqxC6-0004Pk-9u from Yao_Qi@mentor.com for gdb-patches@sourceware.org; Sun, 23 Jun 2013 20:11:54 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Sun, 23 Jun 2013 20:11:54 -0700 Received: from qiyao.dyndns.org.dyndns.org (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.2.247.3; Sun, 23 Jun 2013 20:11:53 -0700 From: Yao Qi To: Subject: [PATCH] Fix up msymbol type of dll trampoline to mst_solib_trampoline Date: Mon, 24 Jun 2013 04:24:00 -0000 Message-ID: <1372043502-4618-1-git-send-email-yao@codesourcery.com> MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2013-06/txt/msg00639.txt.bz2 Hi, I find the following fail when testing native mingw32 gdb, (gdb) br foo Breakpoint 3 at 0x401418 (2 locations) FAIL: gdb.base/solib-symbol.exp: foo in libmd two breakpoint locations are set on "" (the dll trampoline) and "foo" (the function in dll). It is wrong because dll has been loaded, and it is expected to set one breakpoint on "foo" in dll only. Native Linux GDB behaves correctly in this case. When breakpoint is set in CLI, like "b foo", GDB will search the minimal symbols of "foo" when parsing the linespec "foo". During the search, GDB will sort minimal symbols in classification order and only record the minimal symbols with the lowest classification. See how classify_mtype is called in search_minsyms_for_name. On Linux, on this point, there are two minimal symbols "foo" with different types, one is the function in shared lib (mst_text) and the other is the plt stub (mst_solib_trampoline). According to the rule in classify_mtype and algorithm in search_minsyms_for_name, only one minimal symbol, whose type is mst_text, is record, and only one breakpoint location is set on it finally. However, on windows, there are two minimal symbols "foo" too, one is the function in dll, and the other is the dll trampoline (which is similar to plt stub, IMO). The type of both of these minimal symbols is "mst_text", so the have the same priority in classify_mtype, and two of them are recorded. That is the root cause of this problem. I think the right fix could be setting the type of minimal symbol to "mst_solib_trampoline" if it is the dll trampoline. Read the comments to mst_solib_trampoline get this idea confirmed, /* GDB uses mst_solib_trampoline for the start address of a shared library trampoline entry. Breakpoints for shared library functions are put there if the shared library is not yet loaded. After the shared library is loaded, lookup_minimal_symbol will prefer the minimal symbol from the shared library (usually a mst_text symbol) over the mst_solib_trampoline symbol, and the breakpoints will be moved to their true address in the shared library via breakpoint_re_set. */ mst_solib_trampoline, /* Shared library trampoline code */ The rationale of this patch is to fix up the type of minimal symbol to "mst_solib_trampoline" when reading the file if the minimal symbol is a dll trampoline. We find that there is always a symbol "_impl_foo" coexists with dll trampoline "foo" in the current minimal symbols red in. Our approach is to collect all minimal symbols which name has prefix "_imp_", remove the prefix, and find minimal symbols. If found, it is a dll trampoline. For example, there are several symbols, foo, bar, _imp_foo, _imp_baz, we record symbols with "_imp_" prefix in a set {_imp_foo, _imp_baz}, remove prefix {foo, baz}, and look for them in these symbols. Symbol foo is found, and it is a dll trampoline. Regression test mingw32 native gdb with a remote host board file. The fail I mentioned above is fixed. gdb: 2013-06-24 Yao Qi * coffread.c: Use DEF_VEC_P to define vector type. (coff_symtab_read): Define local variable 'dll_trampoline'. Record minimal symbols into 'dll_trampoline' if their names have prefix "_imp_ or "__imp_". Set the type of minimal symbol to 'mst_solib_trampoline' if it is a dll trampoline. * minsyms.c (prim_find_minimal_symbol): New function. * minsyms.h (prim_find_minimal_symbol): Declare. --- gdb/coffread.c | 43 +++++++++++++++++++++++++++++++++++++++++++ gdb/minsyms.c | 27 +++++++++++++++++++++++++++ gdb/minsyms.h | 2 ++ 3 files changed, 72 insertions(+), 0 deletions(-) diff --git a/gdb/coffread.c b/gdb/coffread.c index bf39085..c0f08b8 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -724,6 +724,9 @@ coff_symfile_finish (struct objfile *objfile) } +typedef struct minimal_symbol *msymbolp; +DEF_VEC_P (msymbolp); + /* Given pointers to a symbol table in coff style exec file, analyze them and create struct symtab's describing the symbols. NSYMS is the number of symbols in the symbol table. @@ -757,6 +760,8 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, int val; CORE_ADDR tmpaddr; struct minimal_symbol *msym; + /* A set of minimal_symbol which has prefix "__imp_" or "_imp_". */ + VEC (msymbolp) *name_prefix_imp = NULL; /* Work around a stdio bug in SunOS4.1.1 (this makes me nervous.... it's hard to know I've really worked around it. The fix should @@ -1006,6 +1011,16 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, SYMBOL_VALUE (sym) = tmpaddr; SYMBOL_SECTION (sym) = sec; } + + /* Record minimal symbols which name are prefixed by "__imp_" + or "_imp_" in set NAME_PREFIX_IMP if their type is + mst_data. Note that 'maintenance print msymbols' shows + that type of these "_imp_XXXX" symbols is mst_data. */ + if (msym != NULL && ms_type == mst_data + && (strncmp (cs->c_name, "__imp_", 6) == 0 + || strncmp (cs->c_name, "_imp_", 5) == 0)) + VEC_safe_push (msymbolp, name_prefix_imp, msym); + } break; @@ -1151,6 +1166,34 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, } } + if (pe_file) + { + int ix; + struct minimal_symbol *msym_dll; + + /* Set NAME_PREFIX_IMP contains minimal symbols which name is + prefixed by "__imp_" or "_imp_". In each iteration, look for the + minimal symbols just red in by matching the minimal symbol name + without the prefix. */ + for (ix = 0; + VEC_iterate (msymbolp, name_prefix_imp, ix, msym_dll); + ix++) + { + char *buffer = xstrdup (SYMBOL_LINKAGE_NAME (msym_dll)); + const char *name = (buffer[1] == '_' ? &buffer[7] : &buffer[6]); + struct minimal_symbol *found + = prim_find_minimal_symbol (name); + + /* If found, there are symbols named "_imp_foo" and "foo" + respectively red in from the current objfile. Set the type + of symbol "foo" as 'mst_solib_trampoline'. */ + if (found != NULL && MSYMBOL_TYPE (found) == mst_text) + MSYMBOL_TYPE (found) = mst_solib_trampoline; + + xfree (buffer); + } + } + if ((nsyms == 0) && (pe_file)) { /* We've got no debugging symbols, but it's a portable diff --git a/gdb/minsyms.c b/gdb/minsyms.c index 89e538a..f5c96db 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -1257,6 +1257,33 @@ install_minimal_symbols (struct objfile *objfile) } } +/* Look for the minimal symbol which name is NAME. Return NULL if not + found. */ + +struct minimal_symbol * +prim_find_minimal_symbol (const char *name) +{ + struct msym_bunch *bunch; + int max; + + max = msym_bunch_index; + for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next) + { + int bindex; + + for (bindex = 0; bindex < max; bindex++) + { + struct minimal_symbol *msym = &bunch->contents[bindex]; + + if (strcmp (name, SYMBOL_LINKAGE_NAME (msym)) == 0) + return msym; + } + max = BUNCH_SIZE; + } + + return NULL; +} + /* See minsyms.h. */ void diff --git a/gdb/minsyms.h b/gdb/minsyms.h index 4d48477..137ee00 100644 --- a/gdb/minsyms.h +++ b/gdb/minsyms.h @@ -252,4 +252,6 @@ void iterate_over_minimal_symbols (struct objfile *objf, void *), void *user_data); +struct minimal_symbol* prim_find_minimal_symbol (const char *name); + #endif /* MINSYMS_H */ -- 1.7.7.6