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
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);
}
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.
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!
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