PLUGINS: Formatting.
Misformatted casts in an earier commit, oops. svn-id: r52572
This commit is contained in:
parent
284b23092b
commit
d8b85ffcb8
15 changed files with 192 additions and 169 deletions
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "common/debug.h"
|
||||
|
||||
#define DEBUG_NUM 2
|
||||
|
||||
/**
|
||||
* Follow the instruction of a relocation section.
|
||||
*
|
||||
|
@ -40,7 +42,7 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
Elf32_Rel *rel = 0; // relocation entry
|
||||
|
||||
// Allocate memory for relocation table
|
||||
if (!(rel = (Elf32_Rel *) malloc(size))) {
|
||||
if (!(rel = (Elf32_Rel *)malloc(size))) {
|
||||
warning("elfloader: Out of memory.");
|
||||
return false;
|
||||
}
|
||||
|
@ -69,36 +71,34 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
Elf32_Addr lastHiSymVal = 0;
|
||||
bool hi16InShorts = false;
|
||||
|
||||
#define DEBUG_NUM 2
|
||||
|
||||
// Loop over relocation entries
|
||||
for (uint32 i = 0; i < cnt; i++) {
|
||||
// Get the symbol this relocation entry is referring to
|
||||
Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info));
|
||||
|
||||
// Get the target instruction in the code
|
||||
uint32 *target = (uint32 *) ((byte *)relSegment + rel[i].r_offset);
|
||||
uint32 *target = (uint32 *)((byte *)relSegment + rel[i].r_offset);
|
||||
|
||||
uint32 origTarget = *target; // Save for debugging
|
||||
|
||||
// Act differently based on the type of relocation
|
||||
switch (REL_TYPE(rel[i].r_info)) {
|
||||
case R_MIPS_HI16: // Absolute addressing.
|
||||
case R_MIPS_HI16: // Absolute addressing.
|
||||
if (sym->st_shndx < SHN_LOPROC && // Only shift for plugin section (ie. has a real section index)
|
||||
firstHi16 < 0) { // Only process first in block of HI16s
|
||||
firstHi16 < 0) { // Only process first in block of HI16s
|
||||
firstHi16 = i; // Keep the first Hi16 we saw
|
||||
seenHi16 = true;
|
||||
ahl = (*target & 0xffff) << 16; // Take lower 16 bits shifted up
|
||||
|
||||
lastHiSymVal = sym->st_value;
|
||||
hi16InShorts = ShortsMan.inGeneralSegment((char *) sym->st_value); // Fix for problem with switching btw segments
|
||||
hi16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value); // Fix for problem with switching btw segments
|
||||
if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number
|
||||
debug(8, "elfloader: R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x",
|
||||
i, rel[i].r_offset, ahl, *target);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
|
||||
case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
|
||||
if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index)
|
||||
if (!seenHi16) { // We MUST have seen HI16 first
|
||||
debug(8, "elfloader: R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!", i);
|
||||
|
@ -108,8 +108,8 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
|
||||
// Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
|
||||
// Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
|
||||
// and will be screened out above
|
||||
bool lo16InShorts = ShortsMan.inGeneralSegment((char *) sym->st_value);
|
||||
// and will be screened out above
|
||||
bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
|
||||
|
||||
// Correct the bug by getting the proper value in ahl (taken from the current symbol)
|
||||
if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
|
||||
|
@ -133,12 +133,13 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16)
|
||||
continue; // Skip over non-Hi16s
|
||||
|
||||
lastTarget = (uint32 *) ((char *) relSegment + rel[j].r_offset); // get hi16 target
|
||||
lastTarget = (uint32 *)((char *)relSegment + rel[j].r_offset); // get hi16 target
|
||||
*lastTarget &= 0xffff0000; // Clear the lower 16 bits of the last target
|
||||
*lastTarget |= (relocation >> 16) & 0xffff; // Take the upper 16 bits of the relocation
|
||||
if (relocation & 0x8000)
|
||||
(*lastTarget)++; // Subtle: we need to add 1 to the HI16 in this case
|
||||
}
|
||||
|
||||
firstHi16 = -1; // Reset so we'll know we treated it
|
||||
} else {
|
||||
extendedHi16++;
|
||||
|
@ -148,37 +149,42 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
*target |= relocation & 0xffff; // Take the lower 16 bits of the relocation
|
||||
|
||||
if (debugRelocs[1]++ < DEBUG_NUM)
|
||||
debug(8, "elfloader: R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x",
|
||||
debug(8, "elfloader: R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, "
|
||||
"lastTarget = %x, origt = %x, target = %x",
|
||||
i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
|
||||
|
||||
if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
|
||||
debug(8, "elfloader: R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x",
|
||||
debug(8, "elfloader: R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, "
|
||||
"lastTarget = %x, origt = %x, target = %x",
|
||||
i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_MIPS_26: // Absolute addressing (for jumps and branches only)
|
||||
if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment
|
||||
a = *target & 0x03ffffff; // Get 26 bits' worth of the addend
|
||||
a = (a << 6) >> 6; // Sign extend a
|
||||
case R_MIPS_26: // Absolute addressing (for jumps and branches only)
|
||||
if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment
|
||||
a = *target & 0x03ffffff; // Get 26 bits' worth of the addend
|
||||
a = (a << 6) >> 6; // Sign extend a
|
||||
relocation = ((a << 2) + Elf32_Addr(_segment)) >> 2; // a already points to the target. Subtract our offset
|
||||
*target &= 0xfc000000; // Clean lower 26 target bits
|
||||
*target &= 0xfc000000; // Clean lower 26 target bits
|
||||
*target |= (relocation & 0x03ffffff);
|
||||
|
||||
if (debugRelocs[3]++ < DEBUG_NUM)
|
||||
debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x",
|
||||
debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, "
|
||||
"a=%x, origTarget=%x, target=%x",
|
||||
i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
|
||||
} else {
|
||||
if (debugRelocs[4]++ < DEBUG_NUM)
|
||||
debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x",
|
||||
debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, "
|
||||
"a=%x, origTarget=%x, target=%x",
|
||||
i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
|
||||
}
|
||||
break;
|
||||
|
||||
case R_MIPS_GPREL16: // GP Relative addressing
|
||||
if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section
|
||||
case R_MIPS_GPREL16: // GP Relative addressing
|
||||
if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section
|
||||
ShortsMan.inGeneralSegment((char *) sym->st_value)) { // Only relocate things in the plugin hole
|
||||
a = *target & 0xffff; // Get 16 bits' worth of the addend
|
||||
a = (a << 16) >> 16; // Sign extend it
|
||||
a = *target & 0xffff; // Get 16 bits' worth of the addend
|
||||
a = (a << 16) >> 16; // Sign extend it
|
||||
|
||||
relocation = a + _shortsSegment->getOffset();
|
||||
|
||||
|
@ -186,7 +192,8 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
*target |= relocation & 0xffff;
|
||||
|
||||
if (debugRelocs[5]++ < DEBUG_NUM)
|
||||
debug(8, "elfloader: R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x",
|
||||
debug(8, "elfloader: R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, "
|
||||
"target=%x, offset=%x",
|
||||
i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
|
||||
}
|
||||
|
||||
|
@ -196,15 +203,18 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
|
||||
a = *target; // Get full 32 bits of addend
|
||||
|
||||
if (ShortsMan.inGeneralSegment((char *) sym->st_value)) // Check if we're in the shorts segment
|
||||
relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset
|
||||
else // We're in the main section
|
||||
relocation = a + Elf32_Addr(_segment); // Shift by main offset
|
||||
if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
|
||||
relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset
|
||||
else // We're in the main section
|
||||
relocation = a + Elf32_Addr(_segment); // Shift by main offset
|
||||
|
||||
*target = relocation;
|
||||
|
||||
if (debugRelocs[6]++ < DEBUG_NUM)
|
||||
debug("8, elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x", i, a, origTarget, *target);
|
||||
debug("8, elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x",
|
||||
i, a, origTarget, *target);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -223,20 +233,19 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment)
|
|||
bool MIPSDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
|
||||
// Loop over sections, finding relocation sections
|
||||
for (uint32 i = 0; i < ehdr->e_shnum; i++) {
|
||||
|
||||
Elf32_Shdr *curShdr = &(shdr[i]);
|
||||
//Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
|
||||
|
||||
if (curShdr->sh_type == SHT_REL && // Check for a relocation section
|
||||
curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
|
||||
if (curShdr->sh_type == SHT_REL && // Check for a relocation section
|
||||
curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
|
||||
int32(curShdr->sh_link) == _symtab_sect && // Check that the sh_link connects to our symbol table
|
||||
curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists
|
||||
(shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
|
||||
if (!ShortsMan.inGeneralSegment((char *) shdr[curShdr->sh_info].sh_addr)) { // regular segment
|
||||
(shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
|
||||
if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) { // regular segment
|
||||
if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment))
|
||||
return false;
|
||||
} else { // In Shorts segment
|
||||
if (!relocate(curShdr->sh_offset, curShdr->sh_size, (byte *) _shortsSegment->getOffset()))
|
||||
} else { // In Shorts segment
|
||||
if (!relocate(curShdr->sh_offset, curShdr->sh_size, (byte *)_shortsSegment->getOffset()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -252,14 +261,14 @@ void MIPSDLObject::relocateSymbols(Elf32_Addr offset) {
|
|||
for (uint32 c = _symbol_cnt; c--; s++) {
|
||||
// Make sure we don't relocate special valued symbols
|
||||
if (s->st_shndx < SHN_LOPROC) {
|
||||
if (!ShortsMan.inGeneralSegment((char *) s->st_value)) {
|
||||
if (!ShortsMan.inGeneralSegment((char *)s->st_value)) {
|
||||
s->st_value += offset;
|
||||
|
||||
if (s->st_value < Elf32_Addr(_segment) || s->st_value > Elf32_Addr(_segment) + _segmentSize)
|
||||
warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value);
|
||||
} else { // shorts section
|
||||
s->st_value += _shortsSegment->getOffset();
|
||||
if (!_shortsSegment->inSegment((char *) s->st_value))
|
||||
if (!_shortsSegment->inSegment((char *)s->st_value))
|
||||
warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value);
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +287,7 @@ bool MIPSDLObject::loadSegment(Elf32_Phdr *phdr) {
|
|||
if (phdr->p_align < 0x10000)
|
||||
phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI
|
||||
|
||||
_segment = (byte *) allocSegment(phdr->p_align, phdr->p_memsz + extra);
|
||||
_segment = (byte *)allocSegment(phdr->p_align, phdr->p_memsz + extra);
|
||||
|
||||
if (!_segment) {
|
||||
warning("elfloader: Out of memory.");
|
||||
|
@ -291,16 +300,18 @@ bool MIPSDLObject::loadSegment(Elf32_Phdr *phdr) {
|
|||
baseAddress = _segment + phdr->p_vaddr;
|
||||
_segmentSize = phdr->p_memsz + extra;
|
||||
} else { // This is a shorts section.
|
||||
_shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *) phdr->p_vaddr);
|
||||
_shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr);
|
||||
|
||||
baseAddress = (byte *) _shortsSegment->getStart();
|
||||
baseAddress = (byte *)_shortsSegment->getStart();
|
||||
debug(2, "elfloader: Shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x",
|
||||
_shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset());
|
||||
_shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr,
|
||||
_shortsSegment->getOffset());
|
||||
}
|
||||
|
||||
// Set bss segment to 0 if necessary (assumes bss is at the end)
|
||||
if (phdr->p_memsz > phdr->p_filesz) {
|
||||
debug(2, "elfloader: Setting %p to %p to 0 for bss", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz);
|
||||
debug(2, "elfloader: Setting %p to %p to 0 for bss", baseAddress + phdr->p_filesz,
|
||||
baseAddress + phdr->p_memsz);
|
||||
memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue