R_PPC64_REL24 is reallly "PC-rel. 26 bit, word aligned:
Just like R_PPC_REL24 modified: linker.cpp
This commit is contained in:
parent
fdcdaf596a
commit
fabda4df3a
@ -835,18 +835,27 @@ void ElfLinkerPpc64le::relocate1(const Relocation *rel, byte *location, upx_uint
|
|||||||
/* value will hold relative displacement */
|
/* value will hold relative displacement */
|
||||||
value -= rel->section->offset + rel->offset;
|
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;
|
int displ = (signed char) *location + (int) value;
|
||||||
if (range_check && (displ < -128 || displ > 127))
|
if (range_check && (displ < -128 || displ > 127))
|
||||||
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
|
internal_error("target out of range (%d) in reloc %s:%x\n", displ, rel->section->name,
|
||||||
rel->offset);
|
rel->offset);
|
||||||
*location += value;
|
*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)
|
else if (strcmp(type, "16") == 0)
|
||||||
set_le16(location, get_le16(location) + value);
|
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"
|
else if (strncmp(type, "32", 2) == 0) // for "32" and "32S"
|
||||||
set_le32(location, get_le32(location) + value);
|
set_le32(location, get_le32(location) + value);
|
||||||
else if (strcmp(type, "64") == 0)
|
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);
|
return super::relocate1(rel, location, value, type);
|
||||||
type += 11;
|
type += 11;
|
||||||
|
|
||||||
|
bool range_check = false;
|
||||||
if (strncmp(type, "PC", 2) == 0) {
|
if (strncmp(type, "PC", 2) == 0) {
|
||||||
type += 2;
|
type += 2;
|
||||||
|
range_check = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have "R_PPC64_REL" or "R_PPC64_RELPC" as a prefix.
|
// We have "R_PPC64_REL" or "R_PPC64_RELPC" as a prefix.
|
||||||
/* value will hold relative displacement */
|
/* value will hold relative displacement */
|
||||||
value -= rel->section->offset + rel->offset;
|
value -= rel->section->offset + rel->offset;
|
||||||
|
|
||||||
if (strncmp(type, "14", 2) == 0) // for "14" and "14S"
|
if (strncmp(type, "14", 2) == 0) { // for "14" and "14S"
|
||||||
set_be16(2 + location, get_be16(2 + location) + value);
|
if (3 & value)
|
||||||
else if (strncmp(type, "24", 2) == 0) // for "24" and "24S"
|
internal_error("unaligned word displacement");
|
||||||
set_be24(1 + location, get_be24(1 + location) + value);
|
// 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
|
else
|
||||||
super::relocate1(rel, location, value, type);
|
super::relocate1(rel, location, value, type);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user