Possible to know section of memory a variable is located?

前端 未结 2 1621
情书的邮戳
情书的邮戳 2021-01-22 14:36

Is there any way in a C program to know the section that a variable is in? For example:

char*   str     = "Word1";
char    str2[]  = "Word2";
         


        
2条回答
  •  故里飘歌
    2021-01-22 15:16

    Sections depend on the implementation and I will focus on gcc. You can archieve it but it requires some effort.

    1. If you use your own linker script skip this step. Extract the linker script: ld --verbose > myls.ld. The file will contain more information than only the liner script so you will need to edit it.

    My default linker script:

    OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
              "elf64-x86-64")
    OUTPUT_ARCH(i386:x86-64)
    ENTRY(_start)
    SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
    SECTIONS
    {
      PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
      .interp         : { *(.interp) }
      .note.gnu.build-id  : { *(.note.gnu.build-id) }
      .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) }
      .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.*)
          *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
          *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
          *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
          *(.rela.ifunc)
        }
      .rela.plt       :
        {
          *(.rela.plt)
          PROVIDE_HIDDEN (__rela_iplt_start = .);
          *(.rela.iplt)
          PROVIDE_HIDDEN (__rela_iplt_end = .);
        }
      . = ALIGN(CONSTANT (MAXPAGESIZE));
      .init           :
      {
        KEEP (*(SORT_NONE(.init)))
      }
      .plt            : { *(.plt) *(.iplt) }
    .plt.got        : { *(.plt.got) }
    .plt.sec        : { *(.plt.sec) }
      .text           :
      {
        *(.text.unlikely .text.*_unlikely .text.unlikely.*)
        *(.text.exit .text.exit.*)
        *(.text.startup .text.startup.*)
        *(.text.hot .text.hot.*)
        *(SORT(.text.sorted.*))
        *(.text .stub .text.* .gnu.linkonce.t.*)
        /* .gnu.warning sections are handled specially by elf.em.  */
        *(.gnu.warning)
      }
      .fini           :
      {
        KEEP (*(SORT_NONE(.fini)))
      }
      PROVIDE (__etext = .);
      PROVIDE (_etext = .);
      PROVIDE (etext = .);
      . = ALIGN(CONSTANT (MAXPAGESIZE));
      /* Adjust the address for the rodata segment.  We want to adjust up to
         the same address within the page on the next page up.  */
      . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
      PROVIDE(_RODATA_S = .);
      .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
      .rodata1        : { *(.rodata1) }
      PROVIDE(_RODATA_E = .);
      .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
      .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
      .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
      .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) }
      /* These sections are generated by the Sun/Oracle C++ compiler.  */
      .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
      /* Adjust the address for the data segment.  We want to adjust up to
         the same address within the page on the next page up.  */
      . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
      /* Exception handling  */
      .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
      .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) }
      .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
      .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) }
      /* Thread Local Storage sections  */
      .tdata      :
       {
         PROVIDE_HIDDEN (__tdata_start = .);
         *(.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_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
        KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
        PROVIDE_HIDDEN (__init_array_end = .);
      }
      .fini_array    :
      {
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
        KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
        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 .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
      .dynamic        : { *(.dynamic) }
      .got            : { *(.got) *(.igot) }
      . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
      .got.plt        : { *(.got.plt) *(.igot.plt) }
      .data           :
      {
        *(.data .data.* .gnu.linkonce.d.*)
        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 do not
          pad the .data section.  */
       . = ALIGN(. != 0 ? 64 / 8 : 1);
      }
      .lbss   :
      {
        *(.dynlbss)
        *(.lbss .lbss.* .gnu.linkonce.lb.*)
        *(LARGE_COMMON)
      }
      . = ALIGN(64 / 8);
      . = SEGMENT_START("ldata-segment", .);
      .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
      {
        *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
      }
      .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
      {
        *(.ldata .ldata.* .gnu.linkonce.l.*)
        . = ALIGN(. != 0 ? 64 / 8 : 1);
      }
      . = ALIGN(64 / 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) }
      .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
      /* 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_line.* .debug_line_end) }
      .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) }
      /* DWARF Extension.  */
      .debug_macro    0 : { *(.debug_macro) }
      .debug_addr     0 : { *(.debug_addr) }
      .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
      /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
    }
    
    1. Edit the linker sctript:

    Add the symbols at the beginning and and of the sections you want to check. It is very likely that the default linker script will have those symbols already added.

    In my example, I will add symbols. Here you have what I am adding for .rodata segment. You need to add symbols for all sections you want to trace.

      PROVIDE(_RODATA_S = .);   // <-- added
      .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
      .rodata1        : { *(.rodata1) }
      PROVIDE(_RODATA_E = .);   // <-- added
    
    1. Some C code to detect the section.
    char *x = "AAAAAAAAAAAAAAAAAAAAA";
    char y[] = "BBBBBBBBBBBBBBBBBBBB";
    
    void print(const char *text)
    {
        printf("%s", text);
    }
    
    void (*fp)(const char *) = print;
    
    typedef void myfunc(const char *);
    
    myfunc * const fp1 = print;
    
    extern char _DATA_S[], _edata[],  __executable_start[], _etext[], _RODATA_S[], _RODATA_E[],  __bss_start[], __bss_end[];
    
    
    const char *detect(void *pointer)
    {
        if((uintptr_t)pointer >= (uintptr_t)_DATA_S && (uintptr_t)pointer <= (uintptr_t)_edata)
            return ".data";
        if((uintptr_t)pointer >= (uintptr_t)__executable_start && (uintptr_t)pointer <= (uintptr_t)_etext)
            return ".text";
        if((uintptr_t)pointer >= (uintptr_t)_RODATA_S && (uintptr_t)pointer <= (uintptr_t)_RODATA_E)
            return ".rodata";
        if((uintptr_t)pointer >= (uintptr_t)__bss_start && (uintptr_t)pointer <= (uintptr_t)__bss_end)
            return ".bss";
        return "unknown";
    }
    
    int main(void)
    {
        printf("x points to %s\n", detect(x));
        printf("y points to %s\n", detect(y));
        printf("y is located in %s\n", detect(&y));
        printf("fp points to %s\n", detect((void *)fp));
        printf("fp is located in %s\n", detect((void *)&fp));
        printf("fp1 points to %s\n", detect((void *)fp1));
        printf("fp1 is located in %s\n", detect((void *)&fp1));
    }
    

    compile it: gcc -T"myls.ld" main.c

    When you run it:

    x points to .rodata
    y points to .data
    y is located in .data
    fp points to .text
    fp is located in .data
    fp1 points to .text
    fp1 is located in unknown
    

    PS linker script with my modifications:

    
    OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
              "elf64-x86-64")
    OUTPUT_ARCH(i386:x86-64)
    ENTRY(_start)
    SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
    SECTIONS
    {
      PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
      .interp         : { *(.interp) }
      .note.gnu.build-id  : { *(.note.gnu.build-id) }
      .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) }
      .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.*)
          *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
          *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
          *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
          *(.rela.ifunc)
        }
      .rela.plt       :
        {
          *(.rela.plt)
          PROVIDE_HIDDEN (__rela_iplt_start = .);
          *(.rela.iplt)
          PROVIDE_HIDDEN (__rela_iplt_end = .);
        }
      . = ALIGN(CONSTANT (MAXPAGESIZE));
      .init           :
      {
        KEEP (*(SORT_NONE(.init)))
      }
      .plt            : { *(.plt) *(.iplt) }
    .plt.got        : { *(.plt.got) }
    .plt.sec        : { *(.plt.sec) }
      .text           :
      {
        *(.text.unlikely .text.*_unlikely .text.unlikely.*)
        *(.text.exit .text.exit.*)
        *(.text.startup .text.startup.*)
        *(.text.hot .text.hot.*)
        *(SORT(.text.sorted.*))
        *(.text .stub .text.* .gnu.linkonce.t.*)
        /* .gnu.warning sections are handled specially by elf.em.  */
        *(.gnu.warning)
      }
      .fini           :
      {
        KEEP (*(SORT_NONE(.fini)))
      }
      PROVIDE (__etext = .);
      PROVIDE (_etext = .);
      PROVIDE (etext = .);
      . = ALIGN(CONSTANT (MAXPAGESIZE));
      /* Adjust the address for the rodata segment.  We want to adjust up to
         the same address within the page on the next page up.  */
      . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
      PROVIDE(_RODATA_S = .);
      .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
      .rodata1        : { *(.rodata1) }
      PROVIDE(_RODATA_E = .);
      .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
      .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
      .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
      .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) }
      /* These sections are generated by the Sun/Oracle C++ compiler.  */
      .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
      /* Adjust the address for the data segment.  We want to adjust up to
         the same address within the page on the next page up.  */
      . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
      /* Exception handling  */
      .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
      .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) }
      .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
      .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) }
      /* Thread Local Storage sections  */
      .tdata      :
       {
         PROVIDE_HIDDEN (__tdata_start = .);
         *(.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_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
        KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
        PROVIDE_HIDDEN (__init_array_end = .);
      }
      .fini_array    :
      {
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
        KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
        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 .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
      .dynamic        : { *(.dynamic) }
      .got            : { *(.got) *(.igot) }
      . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
      .got.plt        : { *(.got.plt) *(.igot.plt) }
      PROVIDE(_DATA_S = .);
      .data           :
      {
        *(.data .data.* .gnu.linkonce.d.*)
        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 do not
          pad the .data section.  */
       . = ALIGN(. != 0 ? 64 / 8 : 1);
      }
      __bss_end = .;
      .lbss   :
      {
        *(.dynlbss)
        *(.lbss .lbss.* .gnu.linkonce.lb.*)
        *(LARGE_COMMON)
      }
      . = ALIGN(64 / 8);
      . = SEGMENT_START("ldata-segment", .);
      .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
      {
        *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
      }
      .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
      {
        *(.ldata .ldata.* .gnu.linkonce.l.*)
        . = ALIGN(. != 0 ? 64 / 8 : 1);
      }
      . = ALIGN(64 / 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) }
      .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
      /* 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_line.* .debug_line_end) }
      .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) }
      /* DWARF Extension.  */
      .debug_macro    0 : { *(.debug_macro) }
      .debug_addr     0 : { *(.debug_addr) }
      .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
      /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
    }
    

提交回复
热议问题