Skip to contentSkip to conversation

Problems generating shared library for MIPS using binutils-2.13...

DISCUSSION Steven J. Hill 6 participants 18 messages Oct 25, 2002 – Nov 5, 2002 MIPS

lore
Share & tools
lore
#0 lore raw

Greetings.

I'm doing something stupid here, so please help me out. I am trying to create a shared library with gcc passing parameters to the linker and it is not working.

I compiled all the object files with '-mips2' and then I attempt to create the shared library with:

   mipsel-linux-gcc -shared -Wl,-Amips2,-soname,libz.so.1 \
      -o libz.so.1.1.4 adler32.o compress.o crc32.o gzio.o \
      uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o \
      inftrees.o infcodes.o infutil.o inffast.o

The object files are all mips2, but the generated '.so' object is mips1?! What am I not understanding? I am using binutils-2.13, gcc-3.2 and uClibc-0.9.15. The use of uClibc is not the problem.

-Steve

#1 lore raw
Quoted 9 lines · Steven J. Hill

Greetings.

I'm doing something stupid here, so please help me out. I am trying to create a shared library with gcc passing parameters to the linker and it is not working.

I compiled all the object files with '-mips2' and then I attempt to create the shared library with:

Quoted 8 lines
   mipsel-linux-gcc -shared -Wl,-Amips2,-soname,libz.so.1 \
      -o libz.so.1.1.4 adler32.o compress.o crc32.o gzio.o \
      uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o \
      inftrees.o infcodes.o infutil.o inffast.o

The object files are all mips2, but the generated '.so' object is mips1?! What am I not understanding? I am using binutils-2.13, gcc-3.2 and uClibc-0.9.15. The use of uClibc is not the problem.

More information:

Add -Wl,-v and give us the linker command line.

Is every object or library mentioned on that line already marked as MIPS-2 by readelf? Even crt*, libc*?

Signature · 2 lines
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer
#2 lore raw
Quoted 8 lines · Daniel Jacobowitz

More information:

Add -Wl,-v and give us the linker command line.

Is every object or library mentioned on that line already marked as MIPS-2 by readelf? Even crt*, libc*?

I knew I was being stupid, crt* and libc* are mips1 *sigh*. Looks like I have more work to do for my build system. Below is the verbose output, but I think that's the problem for sure.

-Steve

mipsel-linux-gcc -shared -Wl,-v,-Amips2,-soname,libz.so.1 -o libz.so.1.1.4 adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
collect2 version 3.2 (MIPSel GNU/Linux with ELF)
/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/bin/ld --eh-frame-hdr -EL -shared -o libz.so.1.1.4 /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib/crti.o /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/crtbeginS.o -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2 -L/opt/toolchains/uclibc/bin/../lib/gcc-lib -L/opt/toolchains/uclibc-crosstools-1.0.0/lib/gcc-lib/mipsel-linux/3.2 -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib -L/opt/toolchains/uclibc-crosstools-1.0.0/lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../.. -v -Amips2 -soname libz.so.1 adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o -lgcc -lc -lgcc /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/crtendS.o /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib/crtn.o GNU ld version 2.13

#3 lore raw
Quoted 6 lines · Steven J. Hill
Quoted 3 lines

Is every object or library mentioned on that line already marked as MIPS-2 by readelf? Even crt*, libc*?

I knew I was being stupid, crt* and libc* are mips1 *sigh*. Looks like I have more work to do for my build system. Below is the verbose output, but I think that's the problem for sure.

Hmm, that's strange as a single mips2 object among mips1 ones should make
an executable/shared library be marked as mips2 and not mips1. I wouldn't worry in the long run, though, as I think this should be fixed in the trunk as Richard Sandiford was working in these areas recently. You might want to do a verification to be sure, though.

Signature · 3 lines
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email protected], PGP key available        +
#17 lore raw
In reply to Steven J. Hill
Quoted 9 lines · Steven J. Hill

Greetings.

I'm doing something stupid here, so please help me out. I am trying to create a shared library with gcc passing parameters to the linker and it is not working.

I compiled all the object files with '-mips2' and then I attempt to create the shared library with:

Quoted 9 lines
    mipsel-linux-gcc -shared -Wl,-Amips2,-soname,libz.so.1 \
       -o libz.so.1.1.4 adler32.o compress.o crc32.o gzio.o \
       uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o \
       inftrees.o infcodes.o infutil.o inffast.o

The object files are all mips2, but the generated '.so' object is mips1?! What am I not understanding? I am using binutils-2.13, gcc-3.2 and uClibc-0.9.15. The use of uClibc is not the problem.

That is a bug in the FSF binutils. I believe I fixed it in my Linux binutils:

http://sources.redhat.com/ml/binutils/2001-10/msg00526.html

Please try my Linux binutils.

H.J.

#4 lore raw
In reply to Maciej W. Rozycki
Quoted 10 lines · Maciej W. Rozycki
Quoted 8 lines
Quoted 4 lines

Is every object or library mentioned on that line already marked as MIPS-2 by readelf? Even crt*, libc*?

I knew I was being stupid, crt* and libc* are mips1 *sigh*. Looks like I have more work to do for my build system. Below is the verbose output, but I think that's the problem for sure.

Quoted 6 lines

Hmm, that's strange as a single mips2 object among mips1 ones should make
an executable/shared library be marked as mips2 and not mips1. I wouldn't worry in the long run, though, as I think this should be fixed in the trunk as Richard Sandiford was working in these areas recently. You might want to do a verification to be sure, though.

I tried the trunk and got the same thing. I have made some additional progress. First, I used H.J.Lu's patch for the most part:

http://sources.redhat.com/ml/binutils/2001-10/msg00526.html

Specifically the part:

-  elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
-  elf_elfheader (abfd)->e_flags |= val;
+  if (isa != 0 && (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == 0)

+ {
+ elf_elfheader (abfd)->e_flags &= ~EF_MIPS_ARCH;
+ elf_elfheader (abfd)->e_flags |= isa;
+ }
+
+ if (cpu != 0)
+ {
+ elf_elfheader (abfd)->e_flags &= ~EF_MIPS_MACH;
+ elf_elfheader (abfd)->e_flags |= cpu;
+ }

So, now when I am building 'zlib', the object files get built with:

mipsel-linux-gcc -march=r6000 -fPIC -O3 -DHAVE_UNISTD_H -DUSE_MMAP

and then shared object creation uses:

  mipsel-linux-gcc -shared -Wl,-A,r6000,-v,-soname,libz.so.1 \
    -march=r6000 -o libz.so.1.1.4 adler32.o compress.o crc32.o gzio.o \
    compr.o deflate.o trees.o zutil.o inflate.o infblock.o inftrees.o \
    infcodes.o infutil.o inffast.o

with the verbose output of:

collect2 version 3.2 (MIPSel GNU/Linux with ELF)
/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/bin/ld --eh-frame-hdr -EL -shared -o libz.so.1.1.4 /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib/crti.o /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/crtbeginS.o -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2 -L/opt/toolchains/uclibc/bin/../lib/gcc-lib -L/opt/toolchains/uclibc-crosstools-1.0.0/lib/gcc-lib/mipsel-linux/3.2 -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib -L/opt/toolchains/uclibc-crosstools-1.0.0/lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib -L/opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../.. -A r6000 -v -soname libz.so.1 adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o -lgcc -lc -lgcc /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/crtendS.o /opt/toolchains/uclibc/bin/../lib/gcc-lib/mipsel-linux/3.2/../../../../mipsel-linux/lib/crtn.o

The 'crt*' files and my C runtime are compiled with 'mips1', but as Maciej correctly states in his reply, the output binary should be the highest ISA value when mixing differing ISA objects.

I'm convinced the linker completely ignores '-A' for MIPS. In the '_bfd_mips_elf_final_write_processing' function in 'bfd/elfxx-mips.c' If I print out the EF_MIPS_ARCH flags for the input BFD descriptor. It
is properly set to 'MIPS2', but when the case statement in '_bfd_mips_elf_final_write_processing' is traversed, it uses the R3000/default case which means that the target CPU architecture
didn't get put into the BFD descriptor. So, I instead changed the ISA
if statement above to be:

if (((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) != isa) && (isa
!= 0))

    {
      elf_elfheader (abfd)->e_flags &= ~EF_MIPS_ARCH;
      elf_elfheader (abfd)->e_flags |= isa;
    }

which then properly sets the ISA in the ELF header. My gut feeling though is that we shouldn't have to do this as the target CPU architecture should have been set properly for the incoming BFD. Comments and suggestions welcome. Thanks.

-Steve

#5 lore raw
Quoted 2 lines · Steven J. Hill

I'm convinced the linker completely ignores '-A' for MIPS. In the

-A is for assembler, not linker.

H.J.

#6 lore raw
Quoted 6 lines · H. J. Lu
Quoted 2 lines

I'm convinced the linker completely ignores '-A' for MIPS. In the

-A is for assembler, not linker.

Fine. Still, that doesn't solve the problem, or what I perceive to be a problem. I'll submit my patch and watch it be ignored or for someone to say something.

-Steve

#7 lore raw
Quoted 10 lines · Steven J. Hill
Quoted 6 lines · H. J. Lu
Quoted 2 lines

I'm convinced the linker completely ignores '-A' for MIPS. In the

-A is for assembler, not linker.

Fine. Still, that doesn't solve the problem, or what I perceive to be a problem. I'll submit my patch and watch it be ignored or for someone to say something.

The Linux binutils works fine for me.

H.J.

#8 lore raw
Quoted 8 lines · H. J. Lu
Quoted 4 lines

Fine. Still, that doesn't solve the problem, or what I perceive to be a problem. I'll submit my patch and watch it be ignored or for someone to say something.

The Linux binutils works fine for me.

Really? Good. Go get this tarball:

    ftp://ftp.realitydiluted.com/Linux/MIPS/zlib-1.1.4-mips-prob.tar.bz2

make sure your tools are in your path and just do 'make' and see what ISA your 'libz.so.1.1.4' is. Thanks.

-Steve

#9 lore raw
Quoted 7 lines · Steven J. Hill
Quoted 6 lines · H. J. Lu
Quoted 4 lines

Fine. Still, that doesn't solve the problem, or what I perceive to be a problem. I'll submit my patch and watch it be ignored or for someone to say something.

Quoted 9 lines
Quoted 2 lines

The Linux binutils works fine for me.

Really? Good. Go get this tarball:

     ftp://ftp.realitydiluted.com/Linux/MIPS/zlib-1.1.4-mips-prob.tar.bz2

make sure your tools are in your path and just do 'make' and see what ISA your 'libz.so.1.1.4' is. Thanks.

# readelf -h libz.so.1.1.4
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x14d0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          66196 (bytes into file)
  Flags:                             0x10000003, noreorder, pic, mips2
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         4
  Size of section headers:           40 (bytes)
  Number of section headers:         25
  Section header string table index: 22

H.J.

#10 lore raw
In reply to Steven J. Hill
Quoted 6 lines · Steven J. Hill

In the '_bfd_mips_elf_final_write_processing' function in 'bfd/elfxx-mips.c' If I print out the EF_MIPS_ARCH flags for the input BFD descriptor. It is properly set to 'MIPS2', but when the case statement in '_bfd_mips_elf_final_write_processing' is traversed, it
uses the R3000/default case which means that the target CPU architecture didn't get put into the BFD descriptor.

Is it related to this?

    <http://sources.redhat.com/ml/binutils/2002-10/msg00248.html>

(In the message body, I accidentally copied the code after the patch rather than before. Sorry about that.)

Anyway, that patch won't solve your problem, but the issue seems to be the same: _bfd_mips_elf_merge_private_bfd_data() merges the EF_MIPS_ARCH and EF_MIPS_MACH bits, but _bfd_mips_elf_final_write_processing() overwrites them based on the BFD mach.

Personally, I think _bfd_mips_elf_final_write_processing() is doing the right thing. Surely we ought to be able to set EF_MIPS_ARCH and EF_MIPS_MACH based on the value of bfd_get_mach?

I wonder whether _bfd_mips_elf_merge_private_bfd_data() should be checking for compatibility based on the BFD machs rather than the header flags. It seems a bit odd that we check the ISA level and "machine" separately.

In other words, replace:

  /* Compare the ISA's.  */
  if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
      != (old_flags & (EF_MIPS_ARCH | EF_MIPS_MACH)))
    {
      ...
    }

with code that checks bfd_get_mach (ibfd) against bfd_get_mach (obfd). If ibfd's architecture is an extension of obfd's, copy it to obfd.

Richard

#11 lore raw
Quoted 40 lines · Richard Sandiford
Quoted 6 lines · Steven J. Hill

In the '_bfd_mips_elf_final_write_processing' function in 'bfd/elfxx-mips.c' If I print out the EF_MIPS_ARCH flags for the input BFD descriptor. It is properly set to 'MIPS2', but when the case statement in '_bfd_mips_elf_final_write_processing' is traversed, it
uses the R3000/default case which means that the target CPU architecture didn't get put into the BFD descriptor.

Is it related to this?

    <http://sources.redhat.com/ml/binutils/2002-10/msg00248.html>

(In the message body, I accidentally copied the code after the patch rather than before. Sorry about that.)

Anyway, that patch won't solve your problem, but the issue seems to be the same: _bfd_mips_elf_merge_private_bfd_data() merges the EF_MIPS_ARCH and EF_MIPS_MACH bits, but _bfd_mips_elf_final_write_processing() overwrites them based on the BFD mach.

Personally, I think _bfd_mips_elf_final_write_processing() is doing the right thing. Surely we ought to be able to set EF_MIPS_ARCH and EF_MIPS_MACH based on the value of bfd_get_mach?

I wonder whether _bfd_mips_elf_merge_private_bfd_data() should be checking for compatibility based on the BFD machs rather than the header flags. It seems a bit odd that we check the ISA level and "machine" separately.

In other words, replace:

  /* Compare the ISA's.  */
  if ((new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH))
      != (old_flags & (EF_MIPS_ARCH | EF_MIPS_MACH)))
    {
      ...
    }
Quoted 2 lines

with code that checks bfd_get_mach (ibfd) against bfd_get_mach (obfd). If ibfd's architecture is an extension of obfd's, copy it to obfd.

The FSF binutils has never been right. I have fixed it in my Linux binutils. See my followups on this thread.

H.J.

#12 lore raw
In reply to Richard Sandiford
Quoted 21 lines · Richard Sandiford
Quoted 6 lines · Steven J. Hill

In the '_bfd_mips_elf_final_write_processing' function in 'bfd/elfxx-mips.c' If I print out the EF_MIPS_ARCH flags for the input BFD descriptor. It is properly set to 'MIPS2', but when the case statement in '_bfd_mips_elf_final_write_processing' is traversed, it
uses the R3000/default case which means that the target CPU architecture didn't get put into the BFD descriptor.

Is it related to this?

    <http://sources.redhat.com/ml/binutils/2002-10/msg00248.html>

(In the message body, I accidentally copied the code after the patch rather than before. Sorry about that.)

Anyway, that patch won't solve your problem, but the issue seems to be the same: _bfd_mips_elf_merge_private_bfd_data() merges the EF_MIPS_ARCH and EF_MIPS_MACH bits, but _bfd_mips_elf_final_write_processing() overwrites them based on the BFD mach.

Quoted 4 lines

Personally, I think _bfd_mips_elf_final_write_processing() is doing the right thing. Surely we ought to be able to set EF_MIPS_ARCH and EF_MIPS_MACH based on the value of bfd_get_mach?

Surely we can't... Remember what EF_MIPS_ARCH says: it's actually what we call ISA level elsewhere! I just spent a day beating on this and settled for untagged instead of correctly-tagged binaries; I was trying to built SB-1 binaries (that's EF_MIPS_MACH of EF_MIPS_MACH_SB1) for a 32-bit userland (that's EF_MIPS_ARCH_2). Not just E_MIPS_ABI_O32, but actually -mips2 code.

We can't infer that from the result of bfd_get_mach, I don't think! You're moving in the wrong direction.

Signature · 2 lines
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer
#13 lore raw
Quoted 8 lines · Daniel Jacobowitz

Surely we can't... Remember what EF_MIPS_ARCH says: it's actually what we call ISA level elsewhere! I just spent a day beating on this and settled for untagged instead of correctly-tagged binaries; I was trying to built SB-1 binaries (that's EF_MIPS_MACH of EF_MIPS_MACH_SB1) for a 32-bit userland (that's EF_MIPS_ARCH_2). Not just E_MIPS_ABI_O32, but actually -mips2 code.

Have you tried my Linux binutils? If you follow the release note, it may just work.

H.J.

#14 lore raw
In reply to Daniel Jacobowitz
Quoted 6 lines · Daniel Jacobowitz

Surely we can't... Remember what EF_MIPS_ARCH says: it's actually what we call ISA level elsewhere! I just spent a day beating on this and settled for untagged instead of correctly-tagged binaries; I was trying to built SB-1 binaries (that's EF_MIPS_MACH of EF_MIPS_MACH_SB1) for a 32-bit userland (that's EF_MIPS_ARCH_2). Not just E_MIPS_ABI_O32, but actually -mips2 code.

I'm not sure what you want from a MIPS II SB-1 binary, though. Does it mean that you can't use instructions that are defined in the MIPS32 ISA but not the MIPS II one? But you can use the SB-1-specific instructions (i.e. those not defined in the MIPS64 ISA)?

Richard

#15 lore raw
Quoted 8 lines · Richard Sandiford
Quoted 6 lines · Daniel Jacobowitz

Surely we can't... Remember what EF_MIPS_ARCH says: it's actually what we call ISA level elsewhere! I just spent a day beating on this and settled for untagged instead of correctly-tagged binaries; I was trying to built SB-1 binaries (that's EF_MIPS_MACH of EF_MIPS_MACH_SB1) for a 32-bit userland (that's EF_MIPS_ARCH_2). Not just E_MIPS_ABI_O32, but actually -mips2 code.

Quoted 5 lines

I'm not sure what you want from a MIPS II SB-1 binary, though. Does it mean that you can't use instructions that are defined in the MIPS32 ISA but not the MIPS II one? But you can use the SB-1-specific instructions (i.e. those not defined in the MIPS64 ISA)?

Maybe I'm barking up the wrong tree... yes, it seems that I am....

The principal thing is that I want O32 code. You can't use a higher ISA level than MIPS2 and still use O32, as far as I understand. And this setup has a 32-bit kernel, so using MIPS3/4/64 instructions in userspace is a real losing proposition.

I obviously want -mtune=sb1. So probably I should just be using -mtune=sb1 -mips2. And hack the GENERATE_BRANCHLIKELY test to honor -mtune. Blech, I wish these options were less confusing!

Signature · 2 lines
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer
#16 lore raw
Quoted 6 lines

The principal thing is that I want O32 code. You can't use a higher ISA level than MIPS2 and still use O32, as far as I understand. And this setup has a 32-bit kernel, so using MIPS3/4/64 instructions in userspace is a real losing proposition.

You should be able to do -mips32 -mabi=32, however, I wouldn't bet on this working atm :)

Review

Quoted 4 lines

I obviously want -mtune=sb1. So probably I should just be using

(quoted diff) +0 -2
-mtune=sb1 -mips2.  And hack the GENERATE_BRANCHLIKELY test to honor
-mtune.  Blech, I wish these options were less confusing!

:) Good idea on the GENERATE_BRANCHLIKELY. I think it probably should be dependent on mtune anyhow.

-eric

Signature · 1 line
Yeah, I used to play basketball...