¿Qué significan R X86 64 32S y R X86 64 64 relocation?


Recibí el siguiente error cuando intenté compilar una aplicación C en FreeBSD de 64 bits:

Relocation R_X86_64_32S no se puede usar al hacer un objeto compartido; recompile con-cLPI

¿Qué es R_X86_64_32S la reubicación y qué es R_X86_64_64?

He googleado sobre el error, y es posibles causas - Sería genial si alguien pudiera saber lo que realmente significa R_X86_64_32S.

5 answers

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. Puedes buscarlos todos en el amd64 ABI . Según él, R_X86_64_64 se divide en:

  • R_X86_64-todos los nombres tienen el prefijo
  • 64-Reubicación directa de 64 bits

Y R_X86_64_32S a:

  • R_X86_64-prefijo
  • 32S-truncar el valor a 32 bits y signo-extender

Que básicamente significa " el valor de la símbolo señalado por esta reubicación, más cualquier addend", en ambos casos. Para R_X86_64_32S el enlazador verifica entonces que el signo de valor generado-se extiende al valor original de 64 bits.

Ahora, en un archivo ejecutable, los segmentos de código y datos reciben una dirección base virtual especificada. El código ejecutable no se comparte, y cada ejecutable obtiene su propio espacio de direcciones fresco. Esto significa que el compilador sabe exactamente dónde estará la sección de datos y puede hacer referencia a ella directamente. Bibliotecas, en el por otro lado, solo puede saber que su sección de datos estará en un desplazamiento especificado desde 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 ser producidas con código que pueda ejecutarse sin importar dónde se ponga en memoria, conocido como código independiente de posición (o PIC para abreviar).

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

 32
Author: Michael Foukarakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-14 07:10:07

Para que todo esto tenga sentido, primero debes: {[60]]}

Normas

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

Son todos los valores posibles para el campo ELF32_R_TYPE de una entrada de reubicación, especificados en el System V ABI 4.1 (1997) que especifica las partes neutras de la arquitectura del formato ELF. Ese estándar solo especifica el campo, pero no sus valores arch dependientes.

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:

Las reubicaciones R_X86_64_32 y R_X86_64_32S truncan el valor calculado a 32 bits. El enlazador debe verificar que el valor generado para R_X86_64_32 (R_X86_64_32S) relocation zero-extends (sign-extends) al valor original de 64 bits.

Ejemplo de R_X86_64_64 y R_X86_64_32

Veamos primero 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:

Entonces:

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

Contiene:

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

0000000000000004 <b>:
   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 (que no tiene sentido ya que se trata de datos), y mire solo a las etiquetas, bytes y reubicaciones.

La primera reubicación:

0: R_X86_64_32  .text+0xc

Que significa:

  • 0: actos sobre el byte 0 (etiqueta a)
  • R_X86_64_: prefijo 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 un .long (4 bytes)
  • .text: estamos en la .text sección
  • 0xc: este es el addend, que es un campo de la entrada de reubicación

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

A + S

Donde:

  • A: el addend, 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 la sección .text.

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

R_X86_64_64 es análogo, pero más simple, ya que aquí no hay necesidad de truncar la dirección de s. Esto se indica por el estándar a través de word64 en lugar de word32 en la columna Field.

R_X86_64_32S vs R_X86_64_32

La diferencia entre R_X86_64_32S vs R_X86_64_32 es cuando el enlazador se quejará "con la reubicación truncada para encajar":

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

    Por ejemplo: FF FF FF FF 80 00 00 00 a 80 00 00 00 genera una queja porque FF FF FF FF no es cero.

  • 32S: se queja si el valor truncado después de la reubicación no firme extienda el valor antiguo.

    Por ejemplo: FF FF FF FF 80 00 00 00 a 80 00 00 00 está bien, porque el último bit de 80 00 00 00 y los bits truncados son todos 1.

Ver también: ¿Qué hace este error GCC "... reubicación truncada para encajar..." ¿mala?

R_X86_64_32S se puede generar con:

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

Entonces:

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 el "relocation" truncado para encajar en 32S con un script 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 enlazador a:

. = 0xFFFF0FFF80000000;

Ahora genera el error, porque eso 0 hizo que no fuera una extensión de signo nunca más.

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

 18
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:26

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

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

Necesitas llamar a

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

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

 2
Author: Artyom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-23 06:28:13

Me encontré con este problema y encontré que esta respuesta no me ayudó. Estaba tratando de vincular una biblioteca estática con una biblioteca compartida. También investigué poner el interruptor-cLPI antes en la línea de comandos (como se aconseja en respuestas en otros lugares). Lo único que solucionó el problema, para mí, fue cambiar la biblioteca estática a compartida. Sospecho que el mensaje de error about-cLPI puede ocurrir debido a una serie de causas, pero fundamentalmente lo que desea ver es cómo se están construyendo sus bibliotecas, y desconfíe de las bibliotecas que se están construyendo de diferentes maneras.

 2
Author: jonawebb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-04 20:53:03

En mi caso, el problema surgió porque el programa para compilar esperaba encontrar bibliotecas compartidas en un directorio remoto, mientras que solo las bibliotecas estáticas correspondientes estaban allí en un error.

En realidad, este error de reubicación fue un error de archivo no encontrado disfrazado.

He detallado cómo lo hice frente en este otro hilo https://stackoverflow.com/a/42388145/5459638

 1
Author: XavierStuvw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:00:25