zoukankan      html  css  js  c++  java
  • ld script初探[2]

    a、Q&A

    Q:为什么编出来的应用肯定是在用户地址空间运行,而内核编出来的代码却一定是运行在内核空间?

    A:链接器(Linker):目的是描述输入文件的sections是如何映射到输出文件中,并控制输出文件的内存排列。

    而且ld就是使用这个缺省的script内置在链接器中。

    b、链接脚本具体实践
    链接脚本中无论是输出文件还是输入文件,主要数据是文件中的各种段,把输入文件中的段称为输入段(Input Sections),输出文件中的段称为
    输出段(Output Sections)。
    一般链接脚本名都以lds作为扩展名,ld script

    ld script语法:
    1.语句之间使用分号";"作为分隔符,但是对于命令语句来说也可以使用换行来结束该语句。
    2.脚本文件中使用到的文件名、格式名或段名等凡包含";"或其他的分隔符的,都要使用双引号将该名字全称引用起来。

    实践:hello.c

    #include <stdio.h>

    int main()
    {
    printf("Hello World\n");
    return 0;
    }

    预处理:gcc -E hello.c -o hello.i
    编译:gcc -S hello.i -o hello.s
    汇编:as hello.s -o hello.o
    链接:ld -static -verbose /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginT.o -
    L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib -L/lib hello.o -start-group -lgcc -lgcc_eh -lc -end-group
    /usr/lib/gcc/i386-redhat-linux/4.1.2/crtend.o /usr/lib/crtn.o > 1.txt

    1.txt

    GNU ld version 2.17.50.0.6-9.el5 20061020
    Supported emulations:
    elf_i386
    i386linux
    using internal linker script:
    ==================================================
    /* Script for -z combreloc: combine and sort reloc sections */
    OUTPUT_FORMAT("elf32-i386", "elf32-i386",
    "elf32-i386") ;输出文件使用的BFD格式
    OUTPUT_ARCH(i386) ;设置输出文件的machine architecture
    ENTRY(_start) ;将符号SYMBOL的值设置成入口地址
    SEARCH_DIR("/usr/i386-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); ;定
    义搜索路径
    SECTIONS
    {
    /* Read-only sections, merged into text segment: */
    PROVIDE (__executable_start = 0x08048000); ;PROVIDE关键字用于定义这类符号:在目标文件内被引用,但没有在任何目标文件内被定义
    的符号
    . = 0x08048000 + SIZEOF_HEADERS; ;当前地址为0x08048000 + SIZEOF_HEADERS
    .interp : { *(.interp) }
    .hash : { *(.hash) }
    .gnu.hash : { *(.gnu.hash) }
    .dynsym : { *(.dynsym) }
    .dynstr : { *(.dynstr) }
    .gnu.version : { *(.gnu.version) }
    .gnu.version_d : { *(.gnu.version_d) }
    .gnu.version_r : { *(.gnu.version_r) } ;包含相关的段
    .rel.dyn :
    {
    *(.rel.init)
    *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
    *(.rel.fini)
    *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
    *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
    *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
    *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
    *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
    *(.rel.ctors)
    *(.rel.dtors)
    *(.rel.got)
    *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
    }
    .rela.dyn :
    {
    *(.rela.init)
    *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
    *(.rela.fini)
    *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
    *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
    *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
    *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
    *(.rela.ctors)
    *(.rela.dtors)
    *(.rela.got)
    *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
    }
    .rel.plt : { *(.rel.plt) }
    .rela.plt : { *(.rela.plt) } ;包含相关的段
    .init :
    {
    KEEP (*(.init)) ;KEEP()强制连接器保留一些特定的section
    } =0x90909090
    .plt : { *(.plt) }
    .text :
    {
    *(.text .stub .text.* .gnu.linkonce.t.*)
    KEEP (*(.text.*personality*))
    /* .gnu.warning sections are handled specially by elf32.em. */
    *(.gnu.warning)
    } =0x90909090 ;填充0x9090
    .fini :
    {
    KEEP (*(.fini))
    } =0x90909090
    PROVIDE (__etext = .); ;PROVIDE关键字用于定义这类符号:在目标文件内被引用,但没有在任何目标文件内被定义的符号
    PROVIDE (_etext = .);
    PROVIDE (etext = .);
    .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
    .rodata1 : { *(.rodata1) }
    .eh_frame_hdr : { *(.eh_frame_hdr) }
    .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
    .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
    /* Adjust the address for the data segment. We want to adjust up to
    the same address within the page on the next page up.
    */
    . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . =
    DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
    /* Exception handling */
    .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
    .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
    /* Thread Local Storage sections */
    .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
    .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
    .preinit_array :
    {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    }
    .init_array :
    {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array))
    PROVIDE_HIDDEN (__init_array_end = .);
    }
    .fini_array :
    {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
    }
    .ctors :
    {
    /* gcc uses crtbegin.o to find the start of
    the constructors, so we make sure it is
    first. Because this is a wildcard, it
    doesn't matter if the user does not
    actually link against crtbegin.o; the
    linker won't look for a file to match a
    wildcard. The wildcard also means that it
    doesn't matter which directory crtbegin.o
    is in.
    */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
    the crtend.o file until after the sorted ctors.
    The .ctor section from the crtend file contains the
    end of ctors marker and it must be last
    */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    }
    .dtors :
    {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    }
    .jcr : { KEEP (*(.jcr)) }
    .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
    .dynamic : { *(.dynamic) }
    .got : { *(.got) }
    . = DATA_SEGMENT_RELRO_END (12, .);
    .got.plt : { *(.got.plt) }
    .data :
    {
    *(.data .data.* .gnu.linkonce.d.*)
    KEEP (*(.gnu.linkonce.d.*personality*))
    SORT(CONSTRUCTORS)
    }
    .data1 : { *(.data1) }
    _edata = .; PROVIDE (edata = .);
    __bss_start = .;
    .bss :
    {
    *(.dynbss)
    *(.bss .bss.* .gnu.linkonce.b.*)
    *(COMMON)
    /* Align here to ensure that the .bss section occupies space up to
    _end. Align after .bss to ensure correct alignment even if the
    .bss section disappears because there are no input sections.
    FIXME: Why do we need it? When there is no .bss section, we don't
    pad the .data section.
    */
    . = ALIGN(. != 0 ? 32 / 8 : 1);
    }
    . = ALIGN(32 / 8);
    . = ALIGN(32 / 8);
    _end = .; PROVIDE (end = .);
    . = DATA_SEGMENT_END (.);
    /* Stabs debugging sections. */
    .stab 0 : { *(.stab) }
    .stabstr 0 : { *(.stabstr) }
    .stab.excl 0 : { *(.stab.excl) }
    .stab.exclstr 0 : { *(.stab.exclstr) }
    .stab.index 0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }
    .comment 0 : { *(.comment) }
    /* DWARF debug sections.
    Symbols in the DWARF debugging sections are relative to the beginning
    of the section so we begin them at 0.
    */
    /* DWARF 1 */
    .debug 0 : { *(.debug) }
    .line 0 : { *(.line) }
    /* GNU DWARF 1 extensions */
    .debug_srcinfo 0 : { *(.debug_srcinfo) }
    .debug_sfnames 0 : { *(.debug_sfnames) }
    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges 0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    /* DWARF 2 */
    .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
    .debug_abbrev 0 : { *(.debug_abbrev) }
    .debug_line 0 : { *(.debug_line) }
    .debug_frame 0 : { *(.debug_frame) }
    .debug_str 0 : { *(.debug_str) }
    .debug_loc 0 : { *(.debug_loc) }
    .debug_macinfo 0 : { *(.debug_macinfo) }
    /* SGI/MIPS DWARF 2 extensions */
    .debug_weaknames 0 : { *(.debug_weaknames) }
    .debug_funcnames 0 : { *(.debug_funcnames) }
    .debug_typenames 0 : { *(.debug_typenames) }
    .debug_varnames 0 : { *(.debug_varnames) }
    /* DWARF 3 */
    .debug_pubtypes 0 : { *(.debug_pubtypes) }
    .debug_ranges 0 : { *(.debug_ranges) }
    /DISCARD/ : { *(.note.GNU-stack) }
    }


    ==================================================
    attempt to open /usr/lib/crt1.o succeeded
    /usr/lib/crt1.o
    ........
    /usr/lib/crtn.o

    c、参考链接:
    http://blog.chinaunix.net/space.php?uid=20433875&do=blog&id=1680446
    http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_19486.html
    http://blog.chinaunix.net/space.php?uid=10678279&do=blog&id=2936584
    http://hi.baidu.com/dljaye/blog/item/7b56fb9be84909b9c9eaf486.html
    http://hi.chinaunix.net/?20792635/viewspace-35408
    http://topic.csdn.net/u/20090812/16/d3d9cca2-78d3-4e97-afa4-79fafa439ccc.html
    http://www.linuxeden.com/forum/thread-61470-1-1.html
    程序员自我修养:使用ld链接脚本

  • 相关阅读:
    2020年JVM面试题记录
    Java对象创建过程
    Java内存模型
    JavaMail读取邮件,如何过滤需要的邮件
    Java Mail 邮件 定时收件
    Java很简单的文件上传(transferTo方式)
    Java架构师之必须掌握的10个开源工具
    Java互联网安全项目架构平台设计
    Java互联网安全项目架构设计第一篇
    Apache POI 4.0.1版本 Excel导出数据案例(兼容 xls 和 xlsx)(六)
  • 原文地址:https://www.cnblogs.com/moonflow/p/2312493.html
Copyright © 2011-2022 走看看