From patchwork Thu Dec 16 14:01:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [2/2] Improve reporting of section conflict errors Date: Thu, 16 Dec 2010 04:01:06 -0000 From: Andi Kleen X-Patchwork-Id: 75760 Message-Id: <20101216140106.GB20612@basil.fritz.box> To: Richard Guenther Cc: Andi Kleen , gcc-patches@gcc.gnu.org, Andi Kleen > > >> > >> I agree the patch is useful. > > > > Is that an approval? > > I'd like to see an updated patch with the fixed size array removed. I hadn't planned planned to do that change. Even with a 64bit flags word 1024 is unlikely to be ever exceeded. -Andi here's the current patch: commit 74039621b54efce2a14808a2905367033763f419 Author: Andi Kleen Date: Thu Dec 16 10:38:25 2010 +0100 Improve reporting of section conflict errors When making large projects LTO clean section conflicts can be surprisingly common. Currently they are hard to debug. This patch improves the error reporting a bit by printing out what flags actually differ. It's still not great -- better would be to print the other locations that actually conflict too. But that would be more complicated. Passes bootstrap and full test on x86_64-linux. Ok? gcc/ 2010-12-15 Andi Kleen * varasm.c (section_print_flags): Add. (get_section): Print more details on conflicting flags. diff --git a/gcc/varasm.c b/gcc/varasm.c index ed44610..55dcae3 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -268,6 +268,58 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback) return sect; } +/* Print section flags F into BUF */ + +static char * +section_flags_string (char *buf, unsigned f) +{ + static const struct flag + { + const char *name; + unsigned flag; + unsigned mask; + } flags[] = + { + { "code", SECTION_CODE, 0 }, + { "write", SECTION_WRITE, 0 }, + { "debug", SECTION_DEBUG, 0}, + { "linkonce", SECTION_LINKONCE, 0 }, + { "small", SECTION_SMALL, 0 }, + { "bss", SECTION_BSS, 0 }, + { "forget", SECTION_FORGET, 0 }, + { "merge", SECTION_MERGE, 0 }, + { "strings", SECTION_STRINGS, 0 }, + { "override", SECTION_OVERRIDE, 0 }, + { "tls", SECTION_TLS, 0 }, + { "common", SECTION_COMMON, 0 }, + { "unnamed", SECTION_UNNAMED, SECTION_STYLE_MASK }, + { "named", SECTION_NAMED, SECTION_STYLE_MASK }, + { "noswitch", SECTION_NOSWITCH, SECTION_STYLE_MASK }, + { NULL, 0, 0 } + }; + const struct flag *fl; + char *start = buf; + + buf[0] = 0; + for (fl = &flags[0]; fl->name; fl++) + { + unsigned mask = fl->mask; + + if (mask == 0) + mask = 0xffffffff; + if ((f & mask) & fl->flag) + { + strcpy (buf, fl->name); + strcat (buf, " "); + buf += strlen (buf); + f &= ~fl->flag; + } + } + if (f) + sprintf (buf, "rest %x", f); + return start; +} + /* Return the named section structure associated with NAME. Create a new section with the given fields if no such structure exists. */ @@ -290,15 +342,24 @@ get_section (const char *name, unsigned int flags, tree decl) } else { + unsigned oflags; + sect = *slot; - if ((sect->common.flags & ~SECTION_DECLARED) != flags + oflags = sect->common.flags & ~SECTION_DECLARED; + if (oflags != flags && ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0) { + char buf[1024]; + /* Sanity check user variables for flag changes. */ if (decl == 0) decl = sect->named.decl; gcc_assert (decl); error ("%+D causes a section type conflict", decl); + flags = (oflags ^ flags) & ~SECTION_OVERRIDE; + inform (DECL_SOURCE_LOCATION (decl), + "New section declaration differs in: %s", + section_flags_string (buf, flags)); } } return sect;