R_PPC64_REL24 is reallly "PC-rel. 26 bit, word aligned:

Just like R_PPC_REL24
	modified:   linker.cpp
This commit is contained in:
John Reiser 2024-02-14 11:43:20 -08:00 committed by Markus F.X.J. Oberhumer
parent fdcdaf596a
commit fabda4df3a

View File

@ -835,18 +835,27 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, byte *location, upx_uint
/* value will hold relative displacement */
value -= rel->section->offset + rel->offset;
if (strcmp(type, "8") == 0) {
if (strncmp(type, "14", 2) == 0) { // for "14" and "14S"
if (3 & value)
internal_error("unaligned word displacement");
// FIXME: displacement overflow?
set_le32(location, (0xffff0003 & get_le32(location)) + (0x0000fffc & value));
}
else if (strncmp(type, "24", 2) == 0) { // for "24" and "24S"
if (3 & value)
internal_error("unaligned word displacement");
// FIXME: displacement overflow?
set_le32(location, (0xfc000003 & get_le32(location)) + (0x03fffffc & value));
}
else if (strcmp(type, "8") == 0) {
int displ = (signed char) *location + (int) value;
if (range_check && (displ < -128 || displ > 127))
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
rel->offset);
*location += value;
} else if (strncmp(type, "14", 2) == 0) // for "14" and "14S"
set_le16(location, get_le16(location) + value);
}
else if (strcmp(type, "16") == 0)
set_le16(location, get_le16(location) + value);
else if (strncmp(type, "24", 2) == 0) // for "24" and "24S"
set_le24(location, get_le24(location) + value);
else if (strncmp(type, "32", 2) == 0) // for "32" and "32S"
set_le32(location, get_le32(location) + value);
else if (strcmp(type, "64") == 0)
@ -869,18 +878,41 @@ void ElfLinkerPpc64::relocate1(const Relocation *rel, byte *location, upx_uint64
return super::relocate1(rel, location, value, type);
type += 11;
bool range_check = false;
if (strncmp(type, "PC", 2) == 0) {
type += 2;
range_check = true;
}
// We have "R_PPC64_REL" or "R_PPC64_RELPC" as a prefix.
/* value will hold relative displacement */
value -= rel->section->offset + rel->offset;
if (strncmp(type, "14", 2) == 0) // for "14" and "14S"
set_be16(2 + location, get_be16(2 + location) + value);
else if (strncmp(type, "24", 2) == 0) // for "24" and "24S"
set_be24(1 + location, get_be24(1 + location) + value);
if (strncmp(type, "14", 2) == 0) { // for "14" and "14S"
if (3 & value)
internal_error("unaligned word displacement");
// FIXME: displacement overflow?
set_be32(location, (0xffff0003 & get_be32(location)) + (0x0000fffc & value));
}
else if (strncmp(type, "24", 2) == 0) { // for "24" and "24S"
if (3 & value)
internal_error("unaligned word displacement");
// FIXME: displacement overflow?
set_be32(location, (0xfc000003 & get_be32(location)) + (0x03fffffc & value));
}
else if (strcmp(type, "8") == 0) {
int displ = (signed char) *location + (int) value;
if (range_check && (displ < -128 || displ > 127))
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
rel->offset);
*location += value;
}
else if (strcmp(type, "16") == 0)
set_be16(location, get_be16(location) + value);
else if (strncmp(type, "32", 2) == 0) // for "32" and "32S"
set_be32(location, get_be32(location) + value);
else if (strcmp(type, "64") == 0)
set_be64(location, get_be64(location) + value);
else
super::relocate1(rel, location, value, type);
}