public override ElfSymbol RelocateEntry(Program program, ElfSymbol sym, ElfSection referringSection, ElfRelocation rela) { if (loader.Sections.Count <= sym.SectionIndex) { return(sym); } if (sym.SectionIndex == 0) { return(sym); } var symSection = loader.Sections[(int)sym.SectionIndex]; uint S = (uint)sym.Value; uint A = (uint)rela.Addend; uint P = (uint)rela.Offset; var addr = Address.Ptr32(P); uint PP = P; var arch = program.Architecture; var relR = program.CreateImageReader(arch, addr); var relW = program.CreateImageWriter(arch, addr); var rt = (PpcRt)(rela.Info & 0xFF); switch (rt) { case PpcRt.R_PPC_GLOB_DAT: case PpcRt.R_PPC_COPY: case PpcRt.R_PPC_JMP_SLOT: break; case PpcRt.R_PPC_ADDR32: relW.WriteUInt32(S + A); break; case PpcRt.R_PPC_REL24: uint wInstr = relR.ReadUInt32(); // 24 bit relocation where bits 3-29 are used for relocations uint value = (S + A - P); wInstr = (wInstr & 0xFC000003) | (value & 0x03FFFFFC); relW.WriteUInt32(wInstr); break; case PpcRt.R_PPC_ADDR16_HI: case PpcRt.R_PPC_ADDR16_HA: // Wait for the following R_PPC_ADDR16_LO relocation. prevPpcHi16 = rela; prevRelR = relR; prevRelW = relW; break; case PpcRt.R_PPC_ADDR16_LO: if (prevPpcHi16 == null) { return(sym); } uint valueHi = prevRelR.ReadUInt16(); uint valueLo = relR.ReadUInt16(); if ((PpcRt)(prevPpcHi16.Info & 0xFF) == PpcRt.R_PPC_ADDR16_HA) { valueHi += (valueHi & 0x8000u) != 0 ? 1u : 0u; } value = (valueHi << 16) | valueLo; value += S; valueHi = (value >> 16) & 0xFFFF; valueLo = value & 0xFFFF; prevRelW.WriteBeUInt16((ushort)valueHi); relW.WriteBeUInt16((ushort)valueLo); break; default: if (!missedRelocations.TryGetValue(rt, out var count)) { count = 0; } missedRelocations[rt] = count + 1; break; } return(sym); }