Search code examples
assemblyx86linkerdynamic-linkingdynamic-library

can I link library except specific symbol?


Condition 1. I have myassembly.s which do not have main.

Condition 2. Instead, myassembly.s have global symbol _start.

Condition 3. I wanna link _IO_stdin_used to output binary.

...and here is problematic part.
_IO_stdin_used is asserted on crt1.o as you can see :

jiwon@jiwon:/tmp$ readelf -s /usr/lib/i386-linux-gnu/crt1.o
Symbol table '.symtab' contains 17 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 
     ...
     8: 00000000     4 OBJECT  GLOBAL DEFAULT    4 _fp_hw
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_fini
    10: 00000000     0 FUNC    GLOBAL DEFAULT    2 _start
    11: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_init
    12: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND main
    13: 00000000     0 NOTYPE  WEAK   DEFAULT    6 data_start
    14: 00000000     4 OBJECT  GLOBAL DEFAULT    5 _IO_stdin_used
    15: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_start_main
    16: 00000000     0 NOTYPE  GLOBAL DEFAULT    6 __data_start



Question. Can I link crt1.o without _start?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

...

I attach my situation more specifically as it may be information needed for analysis.

Here is myassembly.s.
As aforementioned situation, It use _start and don't have main.

.global _start
_start:
 push $_STRING1
 push $_STRING2
 call printf
 push $0
 call exit
_STRING1:
 .string "gogo\n"
_STRING2:
 .string "%s"


I assemble and linked it :

jiwon@jiwon:/tmp$ as -o stackoverflow.o stackoverflow.s 
jiwon@jiwon:/tmp$ ld -o stackoverflow -dynamic-linker /lib/ld-linux.so.2  /usr/lib/i386-linux-gnu/crti.o -lc stackoverflow.o /usr/lib/i386-linux-gnu/crtn.o

jiwon@jiwon:/tmp$ ./stackoverflow 
gogo


As you can see above, the output binary works well. However, when I tried crt1.o to be linked, the error happens.

jiwon@jiwon:/tmp$ ld -o stackoverflow -dynamic-linker /lib/ld-linux.so.2  /usr/lib/i386-linux-gnu/crti.o -lc stackoverflow.o /usr/lib/i386-linux-gnu/crtn.o /usr/lib/i386-linux-gnu/crt1.o
/usr/lib/i386-linux-gnu/crt1.o: In function `_start':
(.text+0x0): multiple definition of `_start'
stackoverflow.o:(.text+0x0): first defined here
/usr/lib/i386-linux-gnu/crt1.o: In function `_start':
(.text+0xc): undefined reference to `__libc_csu_fini'
/usr/lib/i386-linux-gnu/crt1.o: In function `_start':
(.text+0x11): undefined reference to `__libc_csu_init'
/usr/lib/i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'



Question (Same) Can I link crt1.o without _start?


Solution

  • Instead of pulling in the whole rat's tail of crt1.o, how about you simply define _IO_stdin_used yourself? Just put this code in one of your assembly files:

            .section .rodata
            .globl _IO_stdin_used
            .type _IO_stdin_used, @object
            .align 4
    _IO_stdin_used:
            .int 0x20001
            .size _IO_stdin_used, 4
    

    Otherwise, if you just want to require the presence of _IO_stdin_used without defining it yourself (for example, because some file in the libc defines it), just put this line into one of your assembly files:

            .globl _IO_stdin_used
    

    This causes the assembler to mark _IO_stdin_used as an undefined global symbol which the linker has to pull in from somewhere.