[Bug c/61395] New: Linker cannot find symbols in object files compiled with recent GCC

2014-06-02 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61395

Bug ID: 61395
   Summary: Linker cannot find symbols in object files compiled
with recent GCC
   Product: gcc
   Version: 4.9.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mimamer at gmail dot com

Apologies in advance for any mistakes in posting this bug report. If what I am
describing is not a bug in GCC please direct me to a place where I can ask for
help on this issue -- thanks!

I recently upgraded from GCC 4.3.4 to 4.9.0, which I set up as a cross compiler
from i686-pc-cygwin to i686-pc-elf together with static and shared libgcc
support. I created a shared libgcc.so version from libgcc.a using 'ld' and
specifying --whole-archive (as well as the other usual flags). Now, when I try
to link even a very simple test program that emits a symbol defined in a shared
library such as libgcc.so the link step fails with GCC/ld complaining that the
symbol (e.g., __divdi3) cannot be found. I can verify that the symbol is
available in libgcc.so's .symtab (as FUNC LOCAL DEFAULT 12) and specified in
main.o's .symtab (as NOTYPE GLOBAL DEFAULT UND), yet when I try to link main.o
with -lgcc (or libgcc.so) I get "Undefined reference to `__divdi3'". Upgrading
the linker did not have any effect. I can also verify that the linker finds all
input files in the right places, so I am completely at lost what is going wrong
here, and though I suspect a compiler bug (since this did work for me with GCC
4.3.4) I may easily be wrong. Apologies again!


[Bug c/61395] Linker cannot find symbols in object files compiled with recent GCC

2014-06-02 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61395

mimamer at gmail dot com changed:

   What|Removed |Added

 Resolution|INVALID |FIXED

--- Comment #2 from mimamer at gmail dot com ---
Well, since this did work for 4.3.4, what is the proper way to build libgcc.so?
No, I cannot specify my own triplet, the target is a custom OS under
development.


[Bug c/61395] Linker cannot find symbols in object files compiled with recent GCC

2014-06-02 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61395

--- Comment #4 from mimamer at gmail dot com ---
I'm sorry to bother you one more time. All symbols are marked as hidden in
libgcc.a, true. But they become "local default" when I create a shared
libgcc.so from it. Just to help me understand what is going on I tried
globalizing the __divdi symbol in my libgcc.so with objcopy, but I still cannot
successfully link it. Why? (Thanks again.) (And btw, creating my own t-* files
seems like horror.)


[Bug c/61395] Linker cannot find symbols in object files compiled with recent GCC

2014-06-02 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61395

mimamer at gmail dot com changed:

   What|Removed |Added

 Status|RESOLVED|CLOSED
 Resolution|FIXED   |INVALID

--- Comment #5 from mimamer at gmail dot com ---
(change status to INVALID, erroneously had it changed before)


[Bug c++/61421] New: Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

Bug ID: 61421
   Summary: Invalid -O2 optimization breaks program
   Product: gcc
   Version: 4.9.0
Status: UNCONFIRMED
  Severity: major
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: mimamer at gmail dot com

Created attachment 32895
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=32895&action=edit
disassembly of faulty binary snippet

It seems that C++ carries out an invalid optimization when compiled with -O2
that breaks the following code snippet:

_dprintf("p %p, n %p, t %p\n", include_list2.head()->prev,
include_list2.head()->next, include_list2.end());
while ( (node = include_list2.dequeue()) != include_list2.end() ) {
//asm volatile("":::"memory");
main_list.insert_at( &iterator->main_node, &node->main_node );
iterator = node;
}
_dprintf("p %p, n %p, t %p\n", include_list2.head()->prev,
include_list2.head()->next, include_list2.end());

Output:
p 0x007f9e44, n 0x007f9e44, t 0x007f9e44
p 0x007f9e44, n 0x, t 0x007f9e44

Expected output:
p 0x007f9e44, n 0x007f9e44, t 0x007f9e44
p 0x007f9e44, n 0x007f9e44, t 0x007f9e44

Explanation: include_list2 implements a simple doubly-linked list, which
happens to be empty at the beginning (i.e., the head's previous and next
pointers both point to the list's anchor, returned by end()). dequeue() thus
should return the anchor, which equals end() (i.e., the while loop should not
be entered). So, nothing should have changed after the loop, yet the anchor's
next pointer suddenly has become zero. Adding the memory barrier (i.e.,
uncommenting the line with the asm statement) gives the expected result.

Disassambled binary output for the snippet is attached, once in its faulty
version and once with the memory barrier. A minimal implementation of list2 is
attached as well. All in one file (why can't I submit more than one?).


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #1 from mimamer at gmail dot com ---
A minimalistic version that breaks with all -O2 flags set:

Starting from an empty main_list:

Node *node;
//asm volatile("":::"memory");
while ( (node = main_list.dequeue()) != main_list.end() )
_dprintf("");

Uncomment the memory barrier and it works.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #2 from mimamer at gmail dot com ---
Turns out the problems arise in different places but only in the
list2::dequeue() function:

inline T *dequeue() {
//asm volatile("":::"memory");
T *head = anchor.next;
anchor.next = head->next;
head->next->prev = (T *)&anchor;
#if 1//(defined(DEBUG) || defined(_DEBUG)) && !defined(NDEBUG)
if ( head != (T *)&anchor )
head->prev = head->next = NULL;
#endif
return head;
};

Uncommenting the memory barrier resolves all issues.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #4 from mimamer at gmail dot com ---
Indeed, this is alias-related. Two questions:

(1) What is a concrete solution for this problem when -fstrict-aliasing is
being used? How should I change my code? (Sorry, I am no expert on this.)

(2) Why is -fno-strict-aliasing being ignored when placed after -O2, just as I
had it all the time in my Makefile?


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #5 from mimamer at gmail dot com ---
T is derived from list2::node, and yes, I'm "up"casting from node to T.
There is no other way around it in the implementation, and if this causes a
problem with aliasing then I don't know what it's good for. Any input
appreciated.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #6 from mimamer at gmail dot com ---
Btw, C++ doesn't give me any aliasing warnings even with -Wstrict-aliasing=1.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #7 from mimamer at gmail dot com ---
Violation of aliasing or not, the problem arises prior to the downcasting from
list2::node* to T*:
T *head = anchor.next;
anchor.next = head->next;
head->next->prev = (T *)&anchor;  // where did head->next become NULL???
where anchor is defined as
struct node {
T*next;
T*prev;
} anchor;
I don't see actually why this should be invalid under any (retarded) aliasing
rules. If Andrew or any of the other experts here could point out to me how the
problem can be solved _without_ fundamentally changing the implementation of
list2 (such as specifying anchor as of type T) I would be very grateful. Thanks
a LOT in advance!

Also, again, why does -fno-strict-aliasing (placed _after_ -O2) not have any
effect?


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #8 from mimamer at gmail dot com ---
As concerns -fno-strict-aliasing, I have to put it before -O2. Sorry for the
mixup.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #9 from mimamer at gmail dot com ---
Now that I have read enough about aliasing rules I realize that they are
considerably fucked up and that their is no way to efficiently downcast without
violating strict aliasing rules. In explanation, you need to copy your data out
and back (which takes time), or implement an instance of a derived class in the
first place (which consumes memory). Yes, my code is efficiency-critical.
Hooray for retarded aliasing rules. (If I don't care about efficiency I could
just as well switch to Java, which gives all the safety that one needs.)


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #11 from mimamer at gmail dot com ---
In short form,

template class list2
{
  public:
struct node {
T*next;
T*prev;
};

nodeanchor;

  public:
/* API */
}

struct Obj : list2::node {
/* obj-specific elements */
}

list2main_list;

So, anchor is of type list2::node while Obj is derived from
list2::node.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #14 from mimamer at gmail dot com ---
Can you explain what you mean by "use type node inside the struct node"?
Because I still cannot see an (efficient) way for solving this problem.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #16 from mimamer at gmail dot com ---
Ah ok, but that doesn't solve my problem as I will eventually need to cast a
node pointer back to T (either at the caller or the callee side). So there _is_
no efficient solution with strict aliasing rules. Which makes it kinda broken,
IMO.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-05 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #18 from mimamer at gmail dot com ---
Ah? I didn't figure that was allowed per strict aliasing rules. But it still
doesn't solve one problem:

inline T *dequeue() {
node *head = anchor.next;
anchor.next = head->next;
head->next->prev = &anchor;
return (T *)head;
};

The last typecast is invalid when the list is empty and thus returns the
anchor, a special element that so far I checked with equality to list2::end():
inline T* end() const { return (T *)&anchor; }

But it is a huge step forward as checking for an empty list in dequeue() is
just ok so as to return NULL instead of the anchor.


[Bug c++/61421] Invalid -O2 optimization breaks program

2014-06-06 Thread mimamer at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61421

--- Comment #19 from mimamer at gmail dot com ---
One last comment on strict aliasing rules: It is ironic that these rules are
supposed to make programs faster, but those developers that really care about
speed are prevented from implementing even moderate optimizations (see
discussion) because of these rules! Again, the concept of strict aliasing rules
is broken.