Possible to know section of memory a variable is located?

前端 未结 2 1618
情书的邮戳
情书的邮戳 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_*) }
    }
    
    0 讨论(0)
  • 2021-01-22 15:22

    It is not possible for a C program to know the section that its variable is in with absolute certainty. It is just like the Heisenberg uncertainty principle - the mere act of taking the address of a variable can make it to exist in memory, when it could otherwise be eliminated completely by optimization.

    Thus use readelf or gdb or objdump, they're decoding the actual executable.

    In principle the ELF headers should be loaded in memory and you can deduce the sections from it, and you could read /proc/xx/maps on Linux and all such, but... unless actually attempting to write a debugger, a garbage collector or such, I wouldn't bother.

    0 讨论(0)
提交回复
热议问题