2013年3月3日 星期日

替換 linux 下的 default linker script

linux default linker script

ld --verbose
  1 GNU ld (GNU Binutils for Debian) 2.22
  2   Supported emulations:
  3    elf_i386
  4    i386linux
  5    elf32_x86_64
  6    elf_x86_64
  7    elf_l1om
  8    elf_k1om
  9 using internal linker script:
 10 ==================================================
 11 /* Script for -z combreloc: combine and sort reloc sections */
 12 OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 13        "elf32-i386")
 14 OUTPUT_ARCH(i386)
 15 ENTRY(_start)
 16 SEARCH_DIR("/usr/i486-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32");
SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32");
SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); 
SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); 
SEARCH_DIR("=/usr/lib");
 17 SECTIONS
 18 {
 19   /* Read-only sections, merged into text segment: */
 20   PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000));
= SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
 21   .interp         : { *(.interp) }
 22   .note.gnu.build-id : { *(.note.gnu.build-id) }
 23   .hash           : { *(.hash) }
 24   .gnu.hash       : { *(.gnu.hash) }
 25   .dynsym         : { *(.dynsym) }
 26   .dynstr         : { *(.dynstr) }
 27   .gnu.version    : { *(.gnu.version) }
 28   .gnu.version_d  : { *(.gnu.version_d) }
 29   .gnu.version_r  : { *(.gnu.version_r) }
 30   .rel.dyn        :
 31     {
 32       *(.rel.init)
 33       *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
 34       *(.rel.fini)
 35       *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
 36       *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
 37       *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
 38       *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
 39       *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
 40       *(.rel.ctors)
 41       *(.rel.dtors)
 42       *(.rel.got)
 43       *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
 44       *(.rel.ifunc)
 45     }
 46   .rel.plt        :
 47     {
 48       *(.rel.plt)
 49       PROVIDE_HIDDEN (__rel_iplt_start = .);
 50       *(.rel.iplt)
 51       PROVIDE_HIDDEN (__rel_iplt_end = .);
 52     }
 53   .init           :
 54   {
 55     KEEP (*(.init))
 56   } =0x90909090
 57   .plt            : { *(.plt) *(.iplt) }
 58   .text           :
 59   {
 60     *(.text.unlikely .text.*_unlikely)
 61     *(.text.exit .text.exit.*)
 62     *(.text.startup .text.startup.*)
 63     *(.text.hot .text.hot.*)
 64     *(.text .stub .text.* .gnu.linkonce.t.*)
 65     /* .gnu.warning sections are handled specially by elf32.em.  */
 66     *(.gnu.warning)
 67   } =0x90909090
 68   .fini           :
 69   {
 70     KEEP (*(.fini))
 71   } =0x90909090
 72   PROVIDE (__etext = .);
 73   PROVIDE (_etext = .);
 74   PROVIDE (etext = .);
 75   .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
 76   .rodata1        : { *(.rodata1) }
 77   .eh_frame_hdr : { *(.eh_frame_hdr) }
 78   .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
 79   .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
 80   .gcc_except_table.*) }
 81   /* These sections are generated by the Sun/Oracle C++ compiler.  */
 82   .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
 83   .exception_ranges*) }
 84   /* Adjust the address for the data segment.  We want to adjust up to
 85      the same address within the page on the next page up.  */
 86   . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
 87   /* Exception handling  */
 88   .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
 89   .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
 90   .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
 91   /* Thread Local Storage sections  */
 92   .tdata   : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
 93   .tbss    : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
 94   .preinit_array     :
 95   {
 96     PROVIDE_HIDDEN (__preinit_array_start = .);
 97     KEEP (*(.preinit_array))
 98     PROVIDE_HIDDEN (__preinit_array_end = .);
 99   }
100   .init_array     :
101   {
102     PROVIDE_HIDDEN (__init_array_start = .);
103     KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
104     KEEP (*(.init_array))
105     KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
106     PROVIDE_HIDDEN (__init_array_end = .);
107   }
108   .fini_array     :
109   {
110     PROVIDE_HIDDEN (__fini_array_start = .);
111     KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
112     KEEP (*(.fini_array))
113     KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
114     PROVIDE_HIDDEN (__fini_array_end = .);
115   }
116   .ctors          :
117   {
118     /* gcc uses crtbegin.o to find the start of
119        the constructors, so we make sure it is
120        first.  Because this is a wildcard, it
121        doesn't matter if the user does not
122        actually link against crtbegin.o; the
123        linker won't look for a file to match a
124        wildcard.  The wildcard also means that it
125        doesn't matter which directory crtbegin.o
126        is in.  */
127     KEEP (*crtbegin.o(.ctors))
128     KEEP (*crtbegin?.o(.ctors))
129     /* We don't want to include the .ctor section from
130        the crtend.o file until after the sorted ctors.
131        The .ctor section from the crtend file contains the
132        end of ctors marker and it must be last */
133     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
134     KEEP (*(SORT(.ctors.*)))
135     KEEP (*(.ctors))
136   }
137   .dtors          :
138   {
139     KEEP (*crtbegin.o(.dtors))
140     KEEP (*crtbegin?.o(.dtors))
141     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
142     KEEP (*(SORT(.dtors.*)))
143     KEEP (*(.dtors))
144   }
145   .jcr            : { KEEP (*(.jcr)) }
146   .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
147   .dynamic        : { *(.dynamic) }
148   .got            : { *(.got) *(.igot) }
149   . = DATA_SEGMENT_RELRO_END (12, .);
150   .got.plt        : { *(.got.plt)  *(.igot.plt) }
151   .data           :
152   {
153     *(.data .data.* .gnu.linkonce.d.*)
154     SORT(CONSTRUCTORS)
155   }
156   .data1          : { *(.data1) }
157   _edata = .; PROVIDE (edata = .);
158   __bss_start = .;
159   .bss            :
160   {
161    *(.dynbss)
162    *(.bss .bss.* .gnu.linkonce.b.*)
163    *(COMMON)
164    /* Align here to ensure that the .bss section occupies space up to
165       _end.  Align after .bss to ensure correct alignment even if the
166       .bss section disappears because there are no input sections.
167       FIXME: Why do we need it? When there is no .bss section, we don't
168       pad the .data section.  */
169    . = ALIGN(. != 0 ? 32 / 8 : 1);
170   }
171   . = ALIGN(32 / 8);
172   . = ALIGN(32 / 8);
173   _end = .; PROVIDE (end = .);
174   . = DATA_SEGMENT_END (.);
175   /* Stabs debugging sections.  */
176   .stab          0 : { *(.stab) }
177   .stabstr       0 : { *(.stabstr) }
178   .stab.excl     0 : { *(.stab.excl) }
179   .stab.exclstr  0 : { *(.stab.exclstr) }
180   .stab.index    0 : { *(.stab.index) }
181   .stab.indexstr 0 : { *(.stab.indexstr) }
182   .comment       0 : { *(.comment) }
183   /* DWARF debug sections.
184      Symbols in the DWARF debugging sections are relative to the beginning
185      of the section so we begin them at 0.  */
186   /* DWARF 1 */
187   .debug          0 : { *(.debug) }
188   .line           0 : { *(.line) }
189   /* GNU DWARF 1 extensions */
190   .debug_srcinfo  0 : { *(.debug_srcinfo) }
191   .debug_sfnames  0 : { *(.debug_sfnames) }
192   /* DWARF 1.1 and DWARF 2 */
193   .debug_aranges  0 : { *(.debug_aranges) }
194   .debug_pubnames 0 : { *(.debug_pubnames) }
195   /* DWARF 2 */
196   .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
197   .debug_abbrev   0 : { *(.debug_abbrev) }
198   .debug_line     0 : { *(.debug_line) }
199   .debug_frame    0 : { *(.debug_frame) }
200   .debug_str      0 : { *(.debug_str) }
201   .debug_loc      0 : { *(.debug_loc) }
202   .debug_macinfo  0 : { *(.debug_macinfo) }
203   /* SGI/MIPS DWARF 2 extensions */
204   .debug_weaknames 0 : { *(.debug_weaknames) }
205   .debug_funcnames 0 : { *(.debug_funcnames) }
206   .debug_typenames 0 : { *(.debug_typenames) }
207   .debug_varnames  0 : { *(.debug_varnames) }
208   /* DWARF 3 */
209   .debug_pubtypes 0 : { *(.debug_pubtypes) }
210   .debug_ranges   0 : { *(.debug_ranges) }
211   .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
212   /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
213 }
214 
215 
216 ==================================================

突然有個想法, 可以寫一個簡單的來代替這個我看不懂的嗎?L4 那個當然是照抄的, 大概猜的出來是幹嘛的, 也是最重要的一個, 試著將 0x08048000 改成別的值, 會得到不同的結果。

l.ld
 1 ENTRY(_start);
 2 SECTIONS
 3 {
 4   PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
 5     .text :
 6     {
 7         _text = .;
 8         *(.text);
 9         _text_end = .;
10     }
11     .data :
12     {
13         _data = .;
14         *(.bss);
15         *(.bss*);
16         *(.data);
17         *(.rodata*);
18         *(COMMON)
19         _data_end = .;
20     }
21 }

所以搞了上面這個, p.S 為測試程式碼。為什麼要用組合語言, 這樣不會有 link c library 的問題, 單純整個測試。
p.S
 1 .section .data
 2 output:
 3   .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
 4 .section .text
 5 .globl _start
 6 _start:
 7   nop
 8   movl $0, %eax
 9   cpuid
10   movl $output, %edi
11   movl %ebx, 28(%edi)
12   movl %edx, 32(%edi)
13   movl %ecx, 36(%edi)
14   movl $4, %eax
15   movl $1, %ebx
16   movl $output, %ecx
17   movl $42, %edx
18   int $0x80
19   movl $1, %eax
20   movl $0, %ebx
21   int $0x80
as p.S -o p.o
ld -m elf_i386 -static -Tl.ld -nostdlib --nmagic -o p p.o
執行結果:
descent@debianlinux:ld_test$ ./p
The processor Vendor ID is 'AuthenticAMD'
真的可以耶! 用來 compiler c 果然出問題, 這就是我沒研究的部份了, 先這樣。
err.c
 1 descent@debianlinux:ld_test$ gcc -static -Tl.ld a.c 
 2 /usr/bin/ld: BFD (GNU Binutils for Debian) 2.22 assertion fail ../../bfd/elf.c:4086
 3 /usr/bin/ld: a.out: section __libc_freeres_ptrs lma 0x80c7554 adjusted to 0x80c756c
 4 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_fini':
 5 (.text+0x6): undefined reference to `__fini_array_end'
 6 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_fini':
 7 (.text+0xc): undefined reference to `__fini_array_start'
 8 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_fini':
 9 (.text+0x1a): undefined reference to `__fini_array_start'
10 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
11 (.text+0x4f): undefined reference to `__preinit_array_end'
12 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
13 (.text+0x59): undefined reference to `__preinit_array_start'
14 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
15 (.text+0x81): undefined reference to `__preinit_array_start'
16 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
17 (.text+0x95): undefined reference to `__init_array_end'
18 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
19 (.text+0x9c): undefined reference to `__init_array_start'
20 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_init':
21 (.text+0xc1): undefined reference to `__init_array_start'
22 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
23 (.text+0xe5): undefined reference to `__rel_iplt_end'
24 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
25 (.text+0xec): undefined reference to `__rel_iplt_start'
26 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
27 (.text+0xfd): undefined reference to `__rel_iplt_start'
28 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
29 (.text+0x106): undefined reference to `__rel_iplt_start'
30 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
31 (.text+0x113): undefined reference to `__rel_iplt_start'
32 /usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/libc.a(elf-init.o): In function `__libc_csu_irel':
33 (.text+0x11b): undefined reference to `__rel_iplt_start'
34 collect2: error: ld returned 1 exit status

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。