¿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.
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]]}
- ver un ejemplo mínimo de reubicación: https://stackoverflow.com/a/30507725/895245
- entender la estructura básica de un archivo ELF: https://stackoverflow.com/a/30648229/895245
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
yR_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 (etiquetaa
) -
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 etiquetas
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
a80 00 00 00
genera una queja porqueFF 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
a80 00 00 00
está bien, porque el último bit de80 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?
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.
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.
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
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