[C / C ++] variables de enlace descripción dinámica y funciones en Linux

En primer lugar, una breve reseña

plataforma 1.Linux, 64

2. Los archivos .so, enlace dinámico

3. Descripción del archivo ELF base

Elf (ejecutable y Linking File Format), es decir, tiene dos vistas, una vista se realiza (también conocido como la carga de programa puede ver, para cargar el archivo en la memoria y puede ejecutar una vista) de la derecha en la figura. Otro vínculo es una vista para su uso en un enlace a la etapa de engarce, a la izquierda en la figura. Figura:

 

En segundo lugar, el ejemplo

fun.h

#ifndef _FUN_H_
#define _FUN_H_

extern int fun_num1;

int fun_print();

#endif

fun.c

#include <stdio.h>

int fun_num1 = 5;

int fun_print() {
    printf("fun_num1 %d\n", fun_num1);
}

fun1.h

#ifndef _FUN1_H_
#define _FUN1_H_

extern int fun1_num1;

int fun1_print();

#endif

fun1.c

#include "fun1.h"

#include <stdio.h>

int fun1_num1 = 3;

int fun1_print() {
    printf("fun1_num1:%d\n", fun1_num1);
}

main.c

#include "fun.h"
#include "fun1.h"

int main() {
    fun1_print();
    fun_print();

    fun1_num1 = 1;
    fun_num1 = 2;
    
    fun1_print();
    fun_print();
    
    return 0;
}

makefile

flag=-g
all:main

main.o:main.c
	gcc -o $@ -c $^ $(flag)

main:main.o libfun.so fun1.o
	gcc -o main_s main.o fun1.o -L ./ -lfun

fun_s.o:fun.h fun.c
	gcc -fPIC -o fun_s.o -c fun.c $(flag)

libfun.so:fun_s.o
	gcc --shared -o $@ $^

fun1.o:fun1.h fun1.c
	gcc -o fun1.o -c fun1.c $(flag)

clean:
	rm -rf *.o *.so

.PHONY:clean

ejecutar:

make
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./main_s

El resultado:

fun1_num1:3
fun_num1 5
fun1_num1:1
fun_num1 2

 

En tercer lugar, la función de enlace dinámico

Estática enlace de función: fun1_print

Dynamic Link función: fun_print

1.gdb main_s, DISA principal

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000400716 <+0>:	push   %rbp
   0x0000000000400717 <+1>:	mov    %rsp,%rbp
   0x000000000040071a <+4>:	mov    $0x0,%eax
   0x000000000040071f <+9>:	callq  0x40075d <fun1_print>
   0x0000000000400724 <+14>:	mov    $0x0,%eax
   0x0000000000400729 <+19>:	callq  0x4005f0 <fun_print@plt>
   0x000000000040072e <+24>:	movl   $0x1,0x200908(%rip)        # 0x601040 <fun1_num1>
   0x0000000000400738 <+34>:	movl   $0x2,0x200906(%rip)        # 0x601048 <fun_num1>
   0x0000000000400742 <+44>:	mov    $0x0,%eax
   0x0000000000400747 <+49>:	callq  0x40075d <fun1_print>
   0x000000000040074c <+54>:	mov    $0x0,%eax
   0x0000000000400751 <+59>:	callq  0x4005f0 <fun_print@plt>
   0x0000000000400756 <+64>:	mov    $0x0,%eax
   0x000000000040075b <+69>:	pop    %rbp
   0x000000000040075c <+70>:	retq   
End of assembler dump.

2. Comprobar los enlaces de las funciones estáticas fun1_print

0x000000000040071f <9>: callq 0x40075d <fun1_print>

3.disas 0x40075d, para ver si la dirección es la dirección de una función fun1_print

Dump of assembler code for function fun1_print:
   0x000000000040075d <+0>:	push   %rbp
   0x000000000040075e <+1>:	mov    %rsp,%rbp
   0x0000000000400761 <+4>:	mov    0x2008d9(%rip),%eax        # 0x601040 <fun1_num1>
   0x0000000000400767 <+10>:	mov    %eax,%esi
   0x0000000000400769 <+12>:	mov    $0x400804,%edi
   0x000000000040076e <+17>:	mov    $0x0,%eax
   0x0000000000400773 <+22>:	callq  0x4005e0 <printf@plt>
   0x0000000000400778 <+27>:	nop
   0x0000000000400779 <+28>:	pop    %rbp
   0x000000000040077a <+29>:	retq   
End of assembler dump.

Puede verse en GDB, dirección fun1_print 0x40075d es función estática, por lo que para el enlace función estática, será capaz de saber la dirección virtual absoluto de la función, se puede llevar a cabo directamente por las llamadas a funciones callq en una etapa de enlace estático.

4. Véase fun_print función dinámica

0x0000000000400729 <19>: callq 0x4005f0 <fun_print @ PLT>

5.disas 0x4005f0, para ver si la dirección es la dirección de una función fun_print

Dump of assembler code for function fun_print@plt:
   0x00000000004005f0 <+0>:	jmpq   *0x200a2a(%rip)        # 0x601020
   0x00000000004005f6 <+6>:	pushq  $0x1
   0x00000000004005fb <+11>:	jmpq   0x4005d0
End of assembler dump.

Podemos ver aquí sólo tres instrucciones, y no hay ningún comando asociado con printf, así que esto no es una función de la dirección de fun_print real.

Las siguientes explicaciones

1) callq 0x4005f0, callq 0x40072e dirección es la siguiente dirección en la pila, a continuación, la ejecución salta a 0x4005f0 una función, cuando un valor por el empuje, el código de dirección será saltar esta función se ha completado, ejecución.

Dump of assembler code for function main:
 ...
   0x0000000000400729 <+19>:	callq  0x4005f0 <fun_print@plt>
   0x000000000040072e <+24>:	movl   $0x1,0x200908(%rip)        # 0x601040 <fun1_num1>
 ...
End of assembler dump.

2) Para fun_print @ plt, esta función es un enlazador dinámico enlazará cada función generada de forma automática, uno a uno. Esto significa que si usted tiene una función como la diversión en la biblioteca compartida es así, entonces el enlace generará automáticamente la diversión @ función PLT, y PLT a la mesa vinculación procedimiento (tablas procedimiento de vinculación, los procedimientos deben estar en lenguaje C es una función de la media), plt medio de la diversión es una función de la agencia. La función principal de esta función está por debajo de dicha.

Dump of assembler code for function fun_print@plt:
   0x00000000004005f0 <+0>:	jmpq   *0x200a2a(%rip)        # 0x601020
   0x00000000004005f6 <+6>:	pushq  $0x1
   0x00000000004005fb <+11>:	jmpq   0x4005d0
End of assembler dump.

jmpq * 0x200a2a (% RIP)

jmpq: un salto hacia atrás como un valor de dirección de acuerdo con el valor de

*: Valor medio se toma como la parte posterior de direcciones, se accede al valor de la dirección utilizando el valor de la dirección de la final

% Rip: es la dirección de la instrucción actual, es necesario tomar nota aquí, cuando después de la instrucción operación de extracción de jmpq * 0x200a2a (% RIP) esta instrucción,% rasgar se ha cambiado para hacer frente a la próxima instrucción salto, y por lo tanto la corriente% rip es 0x4005f6, por lo 0x200a2a (% RIP) = 0x200a2a + 0x4005f6 = 0x601020.

Largo aliento-sobre, 0x601020 dirección es la sección .got.plt, nos dieron media tabla de desplazamiento global, esto se utiliza principalmente para la sección de enlace dinámico, que abordará esta memoria de variables y funciones de enlace dinámico, pero es .got.plt sección PLT a la función global tabla de desplazamiento que utiliza.

Por instrucciones: readelf -SW main_s, .got.plt la dirección (direcciones virtuales) la dirección de comienzo 0x601000, tamaño: 0x30, así 0x601000 ~ 0x601030, 0x601020 en la dirección para que el .got.plt

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
...
  [12] .plt              PROGBITS        00000000004005d0 0005d0 000040 10  AX  0   0 16
  [13] .plt.got          PROGBITS        0000000000400610 000610 000008 00  AX  0   0  8
  [14] .text             PROGBITS        0000000000400620 000620 0001d2 00  AX  0   0 16
...
  [16] .rodata           PROGBITS        0000000000400800 000800 000012 00   A  0   0  4
...
  [23] .got              PROGBITS        0000000000600ff8 000ff8 000008 08  WA  0   0  8
  [24] .got.plt          PROGBITS        0000000000601000 001000 000030 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000601030 001030 000014 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000601048 001044 000008 00  WA  0   0  8
...

3) Comprobar el valor almacenado en la dirección 0x601020, x / 2x 0x601020

(gdb) x/2x 0x601020
0x601020:	0x004005f6	0x00000000

Dirección almacenada valor 0x00000000004005f6, con cuidado se dará cuenta de que ésta es realmente la función fun_print @ PLT jmpq * 0x200a2a (% RIP) la dirección de la siguiente instrucción pushq $ 0x1:

Dump of assembler code for function fun_print@plt:
   ...
   0x00000000004005f6 <+6>:	pushq  $0x1
   0x00000000004005fb <+11>:	jmpq   0x4005d0
End of assembler dump.

Aquí el proceso de vinculación dinámica función puede decir brevemente a continuación, cuando la primera llamada a la función fun_print dinámica, va a saltar en medio de la función de proxy fun_print @ PLT, PLT fun_print @ saltará a .got.plt almacenado valor de dirección, por primera vez, se guarda cuando la dirección de salto fun_print @ plt la siguiente orden, la dirección de la siguiente comando se ejecuta posterior al código enlazador, el enlazador se .so archivo de consulta, la consulta si existen incluido la función fun_print, cuando una consulta a la función fun_print actualizará la dirección correspondiente a la ubicación de .got.plt, entonces la próxima vez que la función se llama, saltará directamente a la dirección de la función, sin la necesidad de investigar atada dado que este retardo es una función de la dinámica de unión

6 una vista esquemática fun_print @ plt donde posterior a la ejecución de la instrucción, por objdump -d main_s (no el BGF)

Disassembly of section .plt:

00000000004005d0 <printf@plt-0x10>:
  4005d0:	ff 35 32 0a 20 00    	pushq  0x200a32(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
  4005d6:	ff 25 34 0a 20 00    	jmpq   *0x200a34(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
  4005dc:	0f 1f 40 00          	nopl   0x0(%rax)

00000000004005e0 <printf@plt>:
  4005e0:	ff 25 32 0a 20 00    	jmpq   *0x200a32(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
  4005e6:	68 00 00 00 00       	pushq  $0x0
  4005eb:	e9 e0 ff ff ff       	jmpq   4005d0 <_init+0x28>

Se puede ver saltará a jmpq 0x4005d0, que es una función de impresión @ PLT-0x10, en una función pública, activado por la llamada de la función enlazador, entonces aquí se puede ver que continuará para saltar a 0x601010, esta vez gDB volver a la vista, ejecute el siguiente comando en el BGF

1) b * _start + 0 (inicio de la ejecución de código de entrada)

2) r principal (para hacer el código realmente cargado, también lo hará el mapeo enlazador ld)

3) x / 2x 0x601010 

(gdb) x/2x 0x601010
0x601010:	0xf7dee870	0x00007fff

4) DISA 0x00007ffff7dee870

(gdb) disas 0x00007ffff7dee870
Dump of assembler code for function _dl_runtime_resolve_avx:
...
   0x00007ffff7dee91e <+174>:	callq  0x7ffff7de69f0 <_dl_fixup>
...
End of assembler dump.

Aquí se puede ver que va a entrar en la función _dl_runtime_resolve_avx enlazador, y pide además _dl_fixup, donde fui a ver ninguna aplicación específica más allá, pero aquí ya saben dará lugar a la ejecución de un enlazador posterior, a continuación, la dirección real es cómo demostrar ante la especulación fun_print cambios a .got.plt en ella, la siguiente continuará

1.1) b * principal de +24 (0x40072e yacía punto de interrupción en su lugar, es la siguiente instrucción después de la finalización de la llamada fun_print @ PLT)

1.2) c (permitir la ejecución de código para 0x40072e)

1.3) x / 2x 0x601020 (ver fun_print @ PLT salto a la dirección almacenada .got.plt valor, lo siguiente puede saber de la actualización 0x00007ffff7bd56e0 0x4005e6 el original)

(gdb) x/2x 0x601020
0x601020:	0xf7bd56e0	0x00007fff

1.4) DISA 0x00007ffff7bd56e0 (se puede saber esto es una función de la fun_print real)

Dump of assembler code for function fun_print:
   0x00007ffff7bd56e0 <+0>:	push   %rbp
   0x00007ffff7bd56e1 <+1>:	mov    %rsp,%rbp
   0x00007ffff7bd56e4 <+4>:	mov    0x2008ed(%rip),%rax        # 0x7ffff7dd5fd8
   0x00007ffff7bd56eb <+11>:	mov    (%rax),%eax
   0x00007ffff7bd56ed <+13>:	mov    %eax,%esi
   0x00007ffff7bd56ef <+15>:	lea    0x17(%rip),%rdi        # 0x7ffff7bd570d
   0x00007ffff7bd56f6 <+22>:	mov    $0x0,%eax
   0x00007ffff7bd56fb <+27>:	callq  0x7ffff7bd55c0 <printf@plt>
   0x00007ffff7bd5700 <+32>:	nop
   0x00007ffff7bd5701 <+33>:	pop    %rbp
   0x00007ffff7bd5702 <+34>:	retq   
End of assembler dump.

1.5) Después de la operación anterior, también confirmado por primera vez para realizar disparadores de función dinámicas la dirección real de la función de consulta dinámica enlazador, a continuación, se actualiza el valor de la dirección almacenada en .got.plt, después de la llamada a la función puede ser directamente salta a la dirección de la función real

 

Dinámica que une cuatro variables

Las variables estáticas enlace: fun1_num1

Las variables dinámicas enlace: fun_num1

0. pre-operación

1) main_s GDB (depuración main_s)

2) b * _start + 0 (punto de rotura en el punto de entrada de código)

3) r (código de ejecución)

1.gdb principales, DISA principal

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000400716 <+0>:	push   %rbp
   0x0000000000400717 <+1>:	mov    %rsp,%rbp
   0x000000000040071a <+4>:	mov    $0x0,%eax
   0x000000000040071f <+9>:	callq  0x40075d <fun1_print>
   0x0000000000400724 <+14>:	mov    $0x0,%eax
   0x0000000000400729 <+19>:	callq  0x4005f0 <fun_print@plt>
   0x000000000040072e <+24>:	movl   $0x1,0x200908(%rip)        # 0x601040 <fun1_num1>
   0x0000000000400738 <+34>:	movl   $0x2,0x200906(%rip)        # 0x601048 <fun_num1>
   0x0000000000400742 <+44>:	mov    $0x0,%eax
   0x0000000000400747 <+49>:	callq  0x40075d <fun1_print>
   0x000000000040074c <+54>:	mov    $0x0,%eax
   0x0000000000400751 <+59>:	callq  0x4005f0 <fun_print@plt>
   0x0000000000400756 <+64>:	mov    $0x0,%eax
   0x000000000040075b <+69>:	pop    %rbp
   0x000000000040075c <+70>:	retq   
End of assembler dump.

2 Ver llamada variable estática

0x000000000040072e <24>: movl $ 0x1,0x200908 (% RIP) # 0x601040 <fun1_num1>

3 x 0x601040

0x601040 <fun1_num1>:	0x00000003

El valor es 3, por lo que los main_s archivo ejecutable, es fun1_num1 direcciones virtuales absolutos para acceder a ella

Ver 4 dinámica de las variables de llamada

0x0000000000400738 <34>: movl $ 0x2,0x200906 (% RIP) # 0x601048 <fun_num1>

5 x 0x601048

0x601048 <fun_num1>:	0x00000005

El valor es 5, por lo que las variables dinámicas main_s archivos factibles, es fun_num1 direcciones virtuales absolutos para acceder a ella, parece que hay una pregunta aquí, no debe ser lo mismo que usted? Cómo va a ser el mismo. Esto es porque los main_s documento final generado, si los enlaces estáticos a útil a una variable global, a continuación, las variables globales se guardan directamente en los main_s segmento de datos, posiblemente en .data (variable inicializada, la estática relativa a si hay un enlace inicialización), puede ser en .bss (variables no inicializadas, si existe un enlace con respecto a la inicialización estática). E independientemente de si estas variables globales se definen en .so, o se definen en el archivo de objeto estático, siempre y cuando hay un uso del fichero objeto estático, no siempre se guarda en un segmento de datos en el archivo ejecutable final. La dirección de destino reubicación entre otros archivos estáticos utilizando direcciones virtuales absolutos de acceso, mientras que otros fichero .so para acceder a las variables globales usando el acceso indirecto. Así que para ver la diferencia, tiene que mirar en el archivo del código de función .so.

6 DISA fun_print

(gdb) disas fun_print
Dump of assembler code for function fun_print:
   0x00007ffff7bd56e0 <+0>:	push   %rbp
   0x00007ffff7bd56e1 <+1>:	mov    %rsp,%rbp
   0x00007ffff7bd56e4 <+4>:	mov    0x2008ed(%rip),%rax        # 0x7ffff7dd5fd8
   0x00007ffff7bd56eb <+11>:	mov    (%rax),%eax
   0x00007ffff7bd56ed <+13>:	mov    %eax,%esi
   0x00007ffff7bd56ef <+15>:	lea    0x17(%rip),%rdi        # 0x7ffff7bd570d
   0x00007ffff7bd56f6 <+22>:	mov    $0x0,%eax
   0x00007ffff7bd56fb <+27>:	callq  0x7ffff7bd55c0 <printf@plt>
   0x00007ffff7bd5700 <+32>:	nop
   0x00007ffff7bd5701 <+33>:	pop    %rbp
   0x00007ffff7bd5702 <+34>:	retq   
End of assembler dump.

0x00007ffff7bd56e4 <4>: mov 0x2008ed (% RIP),% rax # 0x7ffff7dd5fd8

0x00007ffff7bd56eb <11>: mov (% rax),% eax

Aquí se puede ver que hay dos instrucciones, el primer valor se 0x2008ed (rip%) como una dirección 0x7ffff7dd5fd8, el valor de dirección se almacena en el registro rax%, entonces el valor almacenado de% rax como la dirección, a continuación, se refiere al valor almacenado en la dirección de registro en eax, eax es donde impreso el valor final efectivo fun_num1.

1) x / 2x 0x7ffff7dd5fd8

(gdb) x/2x 0x7ffff7dd5fd8
0x7ffff7dd5fd8:	0x00601048	0x00000000

Usted encontrará que la dirección almacenada es 0x601048, exactamente en el valor de la dirección anterior fun_num1

(gdb) disas main
Dump of assembler code for function main:
...
   0x000000000040072e <+24>:	movl   $0x1,0x200908(%rip)        # 0x601040 <fun1_num1>
   0x0000000000400738 <+34>:	movl   $0x2,0x200906(%rip)        # 0x601048 <fun_num1>
...
End of assembler dump.

 Por lo tanto .so variables globales de acceso a archivos se almacenan la dirección de la variable global por una posición, y que la posición es en realidad la sección .got, la función .got.plt por lo tanto, se puede deducir se utiliza para enlazar dinámicamente y .got es un links variable dinámica. A continuación, la función de enlace dinámico es el retraso obligado (que es, por primera vez, antes de que la búsqueda de direcciones de llamada de función), las variables dinámicas que enlace es correcto? Después de mi práctica, nos encontramos con una variable de enlace dinámico se carga en el programa se han llevado a cabo para hacer frente a las variables dinámicas se inicializan cuando la entrada de código _start, y por lo tanto no estará vinculada dinámicamente la unión de retardo variable. Otro puede demostrar mis observaciones

1.1) ps -ef | grep main_s (Consulte ID del proceso)

1.2) cat / proc / PID} {/ mapas (ver la asignación de direcciones a cabo)

00400000-00401000 r-xp 00000000 fd:01 1455595                            /tmp/test/main_s
00600000-00601000 r--p 00000000 fd:01 1455595                            /tmp/test/main_s
00601000-00602000 rw-p 00001000 fd:01 1455595                            /tmp/test/main_s
7ffff780b000-7ffff79cb000 r-xp 00000000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7ffff79cb000-7ffff7bcb000 ---p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7bcb000-7ffff7bcf000 r--p 001c0000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7bcf000-7ffff7bd1000 rw-p 001c4000 fd:01 402248                     /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7bd1000-7ffff7bd5000 rw-p 00000000 00:00 0 
7ffff7bd5000-7ffff7bd6000 r-xp 00000000 fd:01 1455592                    /tmp/test/libfun.so
7ffff7bd6000-7ffff7dd5000 ---p 00001000 fd:01 1455592                    /tmp/test/libfun.so
7ffff7dd5000-7ffff7dd6000 r--p 00000000 fd:01 1455592                    /tmp/test/libfun.so
7ffff7dd6000-7ffff7dd7000 rw-p 00001000 fd:01 1455592                    /tmp/test/libfun.so
7ffff7dd7000-7ffff7dfd000 r-xp 00000000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7fea000-7ffff7fed000 rw-p 00000000 00:00 0 
7ffff7ff6000-7ffff7ff7000 rw-p 00000000 00:00 0 
7ffff7ff7000-7ffff7ffa000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00025000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffd000-7ffff7ffe000 rw-p 00026000 fd:01 402246                     /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Se puede ver 7ffff7dd5000-7ffff7dd6000 r - p 00000000 fd: 01 1455592 /tmp/test/libfun.so es de sólo lectura

La dirección de inicio libfun.so es 0x7ffff7bd5000, se puede calcular que corresponde a la dirección virtual 7ffff7dd5000-7ffff7dd6000 (0x20000-0x21000)

1.3) readelf -SW libfun.so

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
...
  [21] .got              PROGBITS        0000000000200fd0 000fd0 000030 08  WA  0   0  8
  [22] .got.plt          PROGBITS        0000000000201000 001000 000020 08  WA  0   0  8
...

.Got se puede ver entre 0x2000-0x21000, por lo que se .got, por lo que el programa se está ejecutando, no puede ser modificada de sólo lectura, por lo que no se puede retrasar la unión.

.Got.plt se puede ver, mientras que un segmento de la siguiente rw-p, por lo tanto .got.plt es escribible, los datos se puede cambiar mientras se ejecuta el programa, por lo que puede completar el retardo requerido unido condición

 

En quinto lugar, la pregunta y la respuesta

1. Dado que los archivos se comparten archivos, sólo una copia en la memoria física, y el otro es el archivo de modo de asignación de dirección mmap (direcciones virtuales se asignan a la implementación física), entonces se ha de ejecutar el programa, que el proceso de vinculado dinámicamente, como inevitablemente modificar .got archivo de modo mmap asignada y .got.plt los valores almacenados correspondientes para lograr un enlace dinámico, entonces esto no modificar el mmap asignación de dirección dirección física correspondiente para que el archivo todavía? En aquel entonces ejecutar este programa no va a leer el valor de dirección se modifica y se ve afectada por ella?

R: Debido al utilizar mmap, básicamente mediante la propiedad MAP_PRIVATE, es decir, en la copia, copia en escritura con escritura, por lo tanto, una sección de asignación operación de escritura se produce, la copia a una nueva dirección física, esto no será por lo que afectará el valor real de la dirección física del archivo. Por lo tanto, se puede entender como cada proceso que .got, .got.plt son únicos para el proceso, o el proceso de su segmento de datos es exclusivo.

Publicados 140 artículos originales · ganado elogios 28 · vistas 180 000 +

Supongo que te gusta

Origin blog.csdn.net/qq_16097611/article/details/81868861
Recomendado
Clasificación