Saltar al contenido

¿Qué significa la reubicación de R_X86_64_32S y R_X86_64_64?

Te damos la bienvenida a nuestra página, en este sitio hallarás la respuesta de lo que necesitas.

Solución:

los R_X86_64_32S y R_X86_64_64 son nombres de tipos de reubicación, para el código compilado para la arquitectura amd64. Puede buscarlos todos en amd64 ABI. De acuerdo a esto, R_X86_64_64 se desglosa en:

  • R_X86_64: todos los nombres tienen este prefijo
  • 64 – Reubicación directa de 64 bits

y R_X86_64_32S para:

  • R_X86_64 – prefix
  • 32S: truncar el valor a 32 bits y extender el signo

que básicamente significa “el valor del símbolo apuntado por esta reubicación, más cualquier sumando”, en ambos casos. Para R_X86_64_32S el enlazador luego verifica que el signo del valor generado se extiende al valor original de 64 bits.

Ahora, en un archivo ejecutable, el código y los segmentos de datos reciben una dirección base virtual especificada. El código ejecutable no se comparte y cada ejecutable obtiene su propio espacio de direcciones nuevo. Esto significa que el compilador sabe exactamente dónde estará la sección de datos y puede hacer referencia a ella directamente. Las bibliotecas, por otro lado, solo pueden saber que su sección de datos estará en un desplazamiento específico de la dirección base; el valor de esa dirección base solo se puede conocer en tiempo de ejecución. Por lo tanto, todas las bibliotecas deben producirse con código que se pueda ejecutar sin importar dónde se coloque en la memoria, conocido como código independiente de la posición (o PIC para abreviar).

Ahora, cuando se trata de resolver su problema, el mensaje de error habla por sí solo.

Para que todo esto tenga sentido, primero debe:

  • vea un ejemplo mínimo de reubicación: https://stackoverflow.com/a/30507725/895245
  • comprender la estructura básica de un archivo ELF: https://stackoverflow.com/a/30648229/895245

Estándares

R_X86_64_64, R_X86_64_32 y R_X86_64_32S están todos definidos por System V AMD ABI, que contiene las especificaciones AMD64 del formato de archivo ELF.

Todos son valores posibles para el ELF32_R_TYPE campo de una entrada de reubicación, especificado en el Sistema V ABI 4.1 (1997) que especifica las partes neutrales de arquitectura del formato ELF. Ese estándar solo especifica el campo, pero no sus valores dependientes del arco.

En 4.4.1 “Tipos de reubicación” vemos la tabla de resumen:

Name          Field   Calculation
------------  ------  -----------
R_X86_64_64   word64  A + S
R_X86_64_32   word32  A + S
R_X86_64_32S  word32  A + S

Explicaremos esta tabla más adelante.

Y la nota:

los R_X86_64_32 y R_X86_64_32S las reubicaciones truncan el valor calculado a 32 bits. El vinculador debe verificar que el valor generado para la reubicación de R_X86_64_32 (R_X86_64_32S) se extienda por cero (signo de extensión) al valor original de 64 bits.

Ejemplo de R_X86_64_64 y R_X86_64_32

Primero veamos R_X86_64_64 y R_X86_64_32:

.section .text
    /* Both a and b contain the address of s. */
    a: .long s
    b: .quad s
    s:

Luego:

as --64 -o main.o main.S
objdump -dzr main.o

Contiene:

0000000000000000 :
   0:   00 00                   add    %al,(%rax)
                        0: R_X86_64_32  .text+0xc
   2:   00 00                   add    %al,(%rax)

0000000000000004 :
   4:   00 00                   add    %al,(%rax)
                        4: R_X86_64_64  .text+0xc
   6:   00 00                   add    %al,(%rax)
   8:   00 00                   add    %al,(%rax)
   a:   00 00                   add    %al,(%rax)

Probado en Ubuntu 14.04, Binutils 2.24.

Ignore el desmontaje por ahora (lo cual no tiene sentido ya que se trata de datos) y observe solo las etiquetas, los bytes y las reubicaciones.

La primera reubicación:

0: R_X86_64_32  .text+0xc

Lo que significa:

  • 0: actúa sobre el byte 0 (etiqueta a)
  • R_X86_64_: prefix utilizado por todos los tipos de reubicación del sistema AMD64 V ABI
  • 32: la dirección de 64 bits de la etiqueta s se trunca a una dirección de 32 bits porque solo especificamos una .long (4 bytes)
  • .text: estamos en el .text sección
  • 0xc: este es el sumar, que es un campo de la entrada de reubicación

La dirección de la reubicación se calcula como:

A + S

Dónde:

  • A: el sumando, aquí 0xC
  • S: el valor del símbolo antes de la reubicación, aquí 00 00 00 00 == 0

Por lo tanto, después de la reubicación, la nueva dirección será 0xC == 12 bytes en el .text sección.

Esto es exactamente lo que esperamos, ya que s viene después de un .long (4 bytes) y un .quad (8 bytes).

R_X86_64_64 es análogo, pero más simple, ya que aquí no es necesario truncar la dirección de s. Esto está indicado por el estándar mediante word64 en lugar de word32 sobre el Field columna.

R_X86_64_32S frente a R_X86_64_32

La diferencia entre R_X86_64_32S vs R_X86_64_32 es cuando el vinculador se quejará “con la reubicación truncada para ajustarse”:

  • 32: se queja si el valor truncado después de la reubicación no es cero extiende el valor anterior, es decir, los bytes truncados deben ser cero:

    P.ej: FF FF FF FF 80 00 00 00 para 80 00 00 00 genera una denuncia porque FF FF FF FF no es cero.

  • 32S: se queja si el valor truncado después de la reubicación no firmar extender el valor anterior.

    P.ej: FF FF FF FF 80 00 00 00 para 80 00 00 00 está bien, porque el último trozo de 80 00 00 00 y los bits truncados son todos 1.

Consulte también: ¿Qué significa este error de GCC “… reubicación truncada para ajustarse a …”?

R_X86_64_32S se puede generar con:

.section .text
.global _start
_start:
    mov s, %eax
    s:

Luego:

as --64 -o main.o main.S
objdump -dzr main.o

Da:

0000000000000000 <_start>:
   0:   8b 04 25 00 00 00 00    mov    0x0,%eax
                        3: R_X86_64_32S .text+0x7

Ahora podemos observar la “reubicación” truncada para encajar en 32S con un script de enlazador:

SECTIONS

    . = 0xFFFFFFFF80000000;
    .text :
    
        *(*)
    

Ahora:

ld -Tlink.ld a.o

Está bien, porque: 0xFFFFFFFF80000000 se trunca en 80000000, que es una extensión de signo.

Pero si cambiamos el script del enlazador a:

. = 0xFFFF0FFF80000000;

Ahora genera el error, porque ese 0 hizo que ya no fuera una extensión de letrero.

Justificación del uso 32S para el acceso a la memoria pero 32 para inmediatos: ¿Cuándo es mejor para un ensamblador usar la reubicación extendida de signos como R_X86_64_32S en lugar de una extensión cero como R_X86_64_32?

R_X86_64_32S y PIE (ejecutables independientes de la posición

R_X86_64_32S no se puede utilizar en ejecutables independientes de la posición, por ejemplo, hecho con gcc -pie, de lo contrario, el enlace falla con:

relocation R_X86_64_32S against `.text' can not be used when making a PIE object; recompile with -fPIC

l

He proporcionado un ejemplo mínimo que lo explica en: ¿Cuál es la opción -fPIE para ejecutables independientes de la posición en gcc y ld?

Eso significa que compiló un objeto compartido sin usar -fPIC marcar como deberías:

 gcc -shared foo.c -o libfoo.so # Wrong

Necesitas llamar

 gcc -shared -fPIC foo.c -o libfoo.so # Right

En la plataforma ELF (Linux), los objetos compartidos se compilan con código independiente de la posición: código que puede ejecutarse desde cualquier ubicación en la memoria; si no se proporciona esta bandera, el código que se genera depende de la posición, por lo que no es posible usar este código compartido. objeto.

valoraciones y reseñas

Al final de todo puedes encontrar las notas de otros programadores, tú incluso tienes la libertad de dejar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *