Gdzie są zdefiniowane symbole etext, edata i end?

To jest kod z Linuksowej strony man:

#include <stdio.h>
#include <stdlib.h>

extern char etext, edata, end;

int main() {
    printf("First address past:\n");
    printf("    program text (etext)      %10p\n", &etext);
    printf("    initialized data (edata)  %10p\n", &edata);
    printf("    uninitialized data (end)  %10p\n", &end);

    exit(EXIT_SUCCESS);
}

Po uruchomieniu poniższy program generuje następujące dane wyjściowe:

$ ./a.out
First address past:
    program text (etext)       0x8048568
    initialized data (edata)   0x804a01c
    uninitialized data (end)   0x804a024

Gdzie są etext, edata end zdefiniowany ? Jak te symbole są przypisane wartości ? To przez linkera czy coś innego ?

4 answers

Symbole te są zdefiniowane w pliku skryptu linkera .

 6
Author: kgiannakakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-23 10:30:37

Zauważ, że na Mac OS X powyższy kod może nie działać! Zamiast tego możesz mieć:

#include <stdio.h>
#include <stdlib.h>
#include <mach-o/getsect.h>

int main(int argc, char *argv[])
{
    printf("    program text (etext)      %10p\n", (void*)get_etext());
    printf("    initialized data (edata)  %10p\n", (void*)get_edata());
    printf("    uninitialized data (end)  %10p\n", (void*)get_end());

    exit(EXIT_SUCCESS);
}
 7
Author: Reza Toghraee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-08 02:38:12

Symbole te odpowiadają początkom różnych segmentów programu. Są ustawiane przez linkera.

 3
Author: Steve Emmerson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-19 19:40:08

Co robi GCC

Kgiannakakis trochę więcej.

Te symbole są zdefiniowane przez słowo kluczowe PROVIDE skryptu linkera, udokumentowane w https://sourceware.org/binutils/docs-2.25/ld/PROVIDE.html#PROVIDE

Domyślne skrypty są generowane podczas budowania Binutils i osadzane w pliku wykonywalnym ld: zewnętrzne pliki, które mogą być zainstalowane w twojej dystrybucji, jak w /usr/lib/ldscripts, nie są używane domyślnie.

Echo należy użyć skryptu linkera:

ld -verbose | less

W binutils 2.24 zawiera:

.text           :
{
  *(.text.unlikely .text.*_unlikely .text.unlikely.*)
  *(.text.exit .text.exit.*)
  *(.text.startup .text.startup.*)
  *(.text.hot .text.hot.*)
  *(.text .stub .text.* .gnu.linkonce.t.*)
  /* .gnu.warning sections are handled specially by elf32.em.  */
  *(.gnu.warning)
}
.fini           :
{
  KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1        : { *(.rodata1) }

Odkrywamy więc również, że:

  • __etext i _etext będą również działać
  • etext nie jest końcem .text, ale raczej .fini, który zawiera również kod
  • Binutils nie znajduje się na końcu segmentu, z .rodata po nim, ponieważ Binutils zrzuca wszystkie sekcje readonly do tego samego segmentu

PROVIDE generuje słabe symbole: jeśli zdefiniujesz również te symbole w kodzie C, twoja definicja wygra i ukryje ten.

Minimal Linux 32-bit example

Aby naprawdę zrozumieć, jak to działa, lubię tworzyć Minimalne przykłady!

main.S:

.section .text
    /* Exit system call. */
    mov $1, %eax
    /* Exit status. */
    mov sdata, %ebx
    int $0x80
.section .data
    .byte 2

link.ld:

SECTIONS
{
    . = 0x400000;
    .text :
    {
        *(.text)
        sdata = .;
        *(.data)
    }
}

Skompiluj i uruchom:

gas --32 -o main.o main.S
ld -m elf_i386 -o main -T link.ld main.o
./main
echo $?

Wyjście:

 2

Wyjaśnienie: sdata wskazuje na pierwszy bajt początku .data sekcji, która następuje.

Więc kontrolując pierwszy bajt tej sekcji, kontrolujemy status wyjścia!

Ten przykład na GitHub .

 2
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:16:29