On Sat, Oct 03, 2015 at 03:12:16PM -0400, Rich Felker wrote: > On Thu, Oct 01, 2015 at 09:30:17PM -0400, Rich Felker wrote: > > But trying the patch on vanilla GCC trunk without my usual J2 target > > setup revealed some additional issues I need to address. I'm getting > > ICE in the code that generates the libgcc bitshift calls, which > > weren't used on J2. This is my fault for failing to extend the changes > > made to other parts of sh.md to the patterns for the new shifts (the > > same ones that broke the kernel) and perhaps also some other things. > > I'm going to go back and review that code and get it done right before > > resubmitting the patch against trunk. > > I found and fixed the problem, but I have a new concern: calls to the > new shift instructions are using the following address forms: > > -mno-fdpic -fPIC: > .long __ashlsi3_r0@GOTOFF > > -mfdpic: > .long __ashlsi3_r0-(.LPCS1+2) > > Neither of these seems valid. Both assume __ashlsi3_r0 will be defined > in the same DSO, which is not true in general; shared libgcc_s.so > might be in use. In this case the call would need to go through the > PLT, which (for PIC or FDPIC) requires r12 to be loaded with the GOT > address. In the non-FDPIC case, r12 _happens_ to contain the GOT > address just because it was used as an addend to get the function > address from the @GOTOFF address, but this does not seem > safe/reliable. In the FDPIC case there's nothing to cause r12 to > contain the GOT address, and in fact if the function has already made > another function call (which uses and clobbers r12), no code is > generated to save and restore r12 for the libgcc call. > > Calls to other functions lib libgcc (e.g. division) seem to work fine > and either go through the PLT or bypass it and load from the GOT > directly. It's only these new special-calling-convention ones that are > broken, and I can't figure out why...
Hmm, according to sh-protos.h: /* A special function that should be linked statically. These are typically smaller or not much larger than a PLT entry. Some also have a non-standard ABI which precludes dynamic linking. */ SFUNC_STATIC So apparently the strange behavior I observed is intended. Presumably there is some mechanism to ensure that these functions are always static-linked? But I don't see it. The libgcc spec I see is: *libgcc: %{static|static-libgcc:-lgcc -lgcc_eh}%{!static:%{!static-libgcc:%{!shared-libgcc:-lgcc --as-needed -lgcc_s --no-as-needed}%{shared-libgcc:-lgcc_s%{!shared: -lgcc}}}} This explicitly omits -lgcc when -shared-libgcc is used with -shared. Thankfully __ashlsi3_r0 is not exported from libgcc.so.1 (as far as I can tell), so this will just be a link error rather than horribly wrong behavior, but it still seems like there's a bug here unless I'm misunderstanding something. I think the final %{!shared: -lgcc} in the spec is an error and should be replaced by simply -lgcc if there are targets where libgcc.a contains necessary symbols that are not/cannot be defined in libgcc_s.so.1. Rich