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
yR_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 (etiquetaa
)R_X86_64_
: prefix utilizado por todos los tipos de reubicación del sistema AMD64 V ABI32
: la dirección de 64 bits de la etiquetas
se trunca a una dirección de 32 bits porque solo especificamos una.long
(4 bytes).text
: estamos en el.text
sección0xc
: 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
para80 00 00 00
genera una denuncia porqueFF 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
para80 00 00 00
está bien, porque el último trozo de80 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.