/// <summary> /// Remove a specific address /// </summary> /// <param name="address">Address to remove</param> /// <returns>True if removed with success, else false</returns> public bool DeleteRelocation(uint address) { List <Reloc> relocs; // search if 4K address exists if (!pages.TryGetValue((address & 0xFFFFF000) - imageBase, out relocs)) { return(false); } ushort offset = (ushort)(address & 0x0FFF); // search if offset exists foreach (Reloc reloc in relocs) { if (reloc.offset == offset && reloc.type != BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(reloc); virtualSize -= 2; if (relocs.Count % 2 != 0) // align in 32bits { bool isAlignDeleted = false; foreach (Reloc item in relocs) // search if align already exists { if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(item); isAlignDeleted = true; virtualSize -= 2; break; } } if (!isAlignDeleted) // if no align reloc found, add it { Reloc item = new Reloc(); item.offset = 0; item.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(item); virtualSize += 2; } } if (relocs.Count == 0) // remove page if nothing offset { pages.Remove((address & 0xFFFFF000) - imageBase); virtualSize -= 8; } IsNotSaved = true; return(true); } } return(false); }
public RelocationWord(Section secId, Reloc r, int offset) { var secL = Shift.GetRight(0xC0000000); var relL = Shift.GetRight(0x3F000000); Word = ((int)secId << secL) | ((int)r << relL) | offset; Parent = null; }
/// <summary>Creates a <see cref="TargetMachine"/> for the target and specified parameters</summary> /// <param name="context">Context to use for LLVM objects created by this machine</param> /// <param name="triple">Target triple for this machine (e.g. -mtriple)</param> /// <param name="cpu">CPU for this machine (e.g. -mcpu)</param> /// <param name="features">Features for this machine (e.g. -mattr...)</param> /// <param name="optLevel">Optimization level</param> /// <param name="relocationMode">Relocation mode for generated code</param> /// <param name="codeModel"><see cref="CodeModel"/> to use for generated code</param> /// <returns><see cref="TargetMachine"/> based on the specified parameters</returns> public TargetMachine CreateTargetMachine(Context context , string triple , string cpu = null , string features = null , CodeGenOpt optLevel = CodeGenOpt.Default , Reloc relocationMode = Reloc.Default , CodeModel codeModel = CodeModel.Default ) { var targetMachineHandle = NativeMethods.CreateTargetMachine(TargetHandle , triple , cpu ?? string.Empty , features ?? string.Empty , ( LLVMCodeGenOptLevel )optLevel , ( LLVMRelocMode )relocationMode , ( LLVMCodeModel )codeModel ); return(new TargetMachine(context, targetMachineHandle)); }
/// <summary>Creates a <see cref="TargetMachine"/> for the target and specified parameters</summary> /// <param name="triple">Target triple for this machine (e.g. -mtriple)</param> /// <param name="cpu">CPU for this machine (e.g. -mcpu)</param> /// <param name="features">Features for this machine (e.g. -mattr...)</param> /// <param name="optLevel">Optimization level</param> /// <param name="relocationMode">Relocation mode for generated code</param> /// <param name="codeModel"><see cref="CodeModel"/> to use for generated code</param> /// <returns><see cref="TargetMachine"/> based on the specified parameters</returns> public TargetMachine CreateTargetMachine(string triple , string cpu = null , string features = null , CodeGenOpt optLevel = CodeGenOpt.Default , Reloc relocationMode = Reloc.Default , CodeModel codeModel = CodeModel.Default ) { triple.ValidateNotNullOrWhiteSpace(nameof(triple)); optLevel.ValidateDefined(nameof(optLevel)); relocationMode.ValidateDefined(nameof(relocationMode)); codeModel.ValidateDefined(nameof(codeModel)); var targetMachineHandle = LLVMCreateTargetMachine(TargetHandle , triple , cpu ?? string.Empty , features ?? string.Empty , ( LLVMCodeGenOptLevel )optLevel , ( LLVMRelocMode )relocationMode , ( LLVMCodeModel )codeModel ); return(new TargetMachine(targetMachineHandle)); }
/// <summary> /// Open the file specified into the <paramref name="path"/>, read the relocation section /// and load it. /// </summary> /// <param name="path"></param> public Relocations(string path) { if (!File.Exists(path)) { throw new FileNotFoundException(); } this.path = path; this.IsNotSaved = false; BinaryReader br = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)); if (br.ReadInt16() != 0x5A4D) // MZ signature { br.Close(); throw new InvalidOperationException("MZ"); } br.BaseStream.Seek(0x3C, SeekOrigin.Begin); // go to ptr to COFF File Header br.BaseStream.Seek(br.ReadInt32(), SeekOrigin.Begin); // go to COFF File Header if (br.ReadInt32() != 0x00004550) // PE\0\0 { br.Close(); throw new InvalidOperationException("PE"); } br.ReadUInt16(); // machine ID. Ignored uint numbersOfSections = br.ReadUInt16(); br.BaseStream.Seek(20 - 4, SeekOrigin.Current); // go to magic number (PE or PE+ = x86 or x64) if (br.ReadInt16() != 0x010B) { br.Close(); throw new InvalidOperationException("X86"); } br.BaseStream.Seek(26, SeekOrigin.Current); // go to ImageBase imageBase = br.ReadUInt32(); br.BaseStream.Seek(64 + 40, SeekOrigin.Current); // go to Data Directories -> Base Relocation Table virtualAddress = br.ReadUInt32(); addressVirtualSize = br.BaseStream.Position; virtualSize = br.ReadUInt32(); br.BaseStream.Seek(80, SeekOrigin.Current); // jump to Section Table // find the RAW address/size RawAddress = 0; RawSize = 0; for (int i = 0; i < numbersOfSections; i++) { br.BaseStream.Seek(12, SeekOrigin.Current); if (br.ReadUInt32() == virtualAddress) { RawSize = br.ReadUInt32(); RawAddress = br.ReadUInt32(); break; } br.BaseStream.Seek(24, SeekOrigin.Current); // place the pointer to the next section } if (RawAddress == 0x00 || RawSize == 0x00) { br.Close(); throw new InvalidOperationException("RAW"); } // reading relocation section br.BaseStream.Seek(RawAddress, SeekOrigin.Begin); pages = new SortedDictionary <uint, List <Reloc> >(); while (br.BaseStream.Position < RawAddress + virtualSize) // 4K block loop { uint address = br.ReadUInt32(); uint size = br.ReadUInt32(); uint count = (size - 8) / 2; List <Reloc> relocs = new List <Reloc>(); for (int i = 0; i < count; i++) // offsets loop { ushort data = br.ReadUInt16(); BASE_RELOCATION_TYPE type = (BASE_RELOCATION_TYPE)((data & 0xF000) >> 12); ushort offset = (ushort)(data & 0x0FFF); Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); } pages.Add(address, relocs); } br.Close(); }
/// <summary> /// Add a relocation address /// </summary> /// <param name="address">Address to add</param> /// <param name="type">Type of relocation</param> /// <returns>-1 if duplicated, 0 if not added, 1 if added a page and 2 if added only in reloc of page</returns> public int AddRelocation(uint address, BASE_RELOCATION_TYPE type) { if (address < imageBase) { return(0); } uint page = (address & 0xFFFFF000) - imageBase; ushort offset = (ushort)(address & 0x00000FFF); if (!pages.ContainsKey(page)) // create a new page if doesn't exists { if (RawSize - virtualSize < 12) { return(0); } List <Reloc> relocs = new List <Reloc>(); Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); reloc = new Reloc(); reloc.offset = 0; reloc.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(reloc); pages.Add(page, relocs); virtualSize += 12; IsNotSaved = true; return(1); } else // just added the offset { List <Reloc> relocs; if (!pages.TryGetValue(page, out relocs)) { return(0); } foreach (Reloc item in relocs) // search if address already present { if (item.offset == offset && item.type != BASE_RELOCATION_TYPE.ABSOLUTE) { return(-1); } } if (relocs.Count % 2 == 0) // align in 32bits { bool isAlignDeleted = false; foreach (Reloc item in relocs) // search if align already exists { if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(item); isAlignDeleted = true; virtualSize -= 2; break; } } if (!isAlignDeleted) // if no align reloc found, add it { if (RawSize - virtualSize < 4) { return(0); } Reloc item = new Reloc(); item.offset = 0; item.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(item); virtualSize += 2; } } Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); virtualSize += 2; IsNotSaved = true; return(2); } }
/// <summary> /// Open the file specified into the <paramref name="path"/>, read the relocation section /// and load it. /// </summary> /// <param name="path"></param> public Relocations(string path) { if (!File.Exists(path)) throw new FileNotFoundException(); this.path = path; this.IsNotSaved = false; BinaryReader br = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)); if (br.ReadInt16() != 0x5A4D) // MZ signature { br.Close(); throw new InvalidOperationException("MZ"); } br.BaseStream.Seek(0x3C, SeekOrigin.Begin); // go to ptr to COFF File Header br.BaseStream.Seek(br.ReadInt32(), SeekOrigin.Begin); // go to COFF File Header if (br.ReadInt32() != 0x00004550) // PE\0\0 { br.Close(); throw new InvalidOperationException("PE"); } br.ReadUInt16(); // machine ID. Ignored uint numbersOfSections = br.ReadUInt16(); br.BaseStream.Seek(20 - 4, SeekOrigin.Current); // go to magic number (PE or PE+ = x86 or x64) if (br.ReadInt16() != 0x010B) { br.Close(); throw new InvalidOperationException("X86"); } br.BaseStream.Seek(26, SeekOrigin.Current); // go to ImageBase imageBase = br.ReadUInt32(); br.BaseStream.Seek(64 + 40, SeekOrigin.Current); // go to Data Directories -> Base Relocation Table virtualAddress = br.ReadUInt32(); addressVirtualSize = br.BaseStream.Position; virtualSize = br.ReadUInt32(); br.BaseStream.Seek(80, SeekOrigin.Current); // jump to Section Table // find the RAW address/size RawAddress = 0; RawSize = 0; for (int i = 0; i < numbersOfSections; i++) { br.BaseStream.Seek(12, SeekOrigin.Current); if (br.ReadUInt32() == virtualAddress) { RawSize = br.ReadUInt32(); RawAddress = br.ReadUInt32(); break; } br.BaseStream.Seek(24, SeekOrigin.Current); // place the pointer to the next section } if (RawAddress == 0x00 || RawSize == 0x00) { br.Close(); throw new InvalidOperationException("RAW"); } // reading relocation section br.BaseStream.Seek(RawAddress, SeekOrigin.Begin); pages = new SortedDictionary<uint, List<Reloc>>(); while (br.BaseStream.Position < RawAddress + virtualSize) // 4K block loop { uint address = br.ReadUInt32(); uint size = br.ReadUInt32(); uint count = (size - 8) / 2; List<Reloc> relocs = new List<Reloc>(); for (int i = 0; i < count; i++) // offsets loop { ushort data = br.ReadUInt16(); BASE_RELOCATION_TYPE type = (BASE_RELOCATION_TYPE)((data & 0xF000) >> 12); ushort offset = (ushort)(data & 0x0FFF); Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); } pages.Add(address, relocs); } br.Close(); }
/// <summary> /// Remove a specific address /// </summary> /// <param name="address">Address to remove</param> /// <returns>True if removed with success, else false</returns> public bool DeleteRelocation(uint address) { List<Reloc> relocs; // search if 4K address exists if (!pages.TryGetValue((address & 0xFFFFF000) - imageBase, out relocs)) return false; ushort offset = (ushort)(address & 0x0FFF); // search if offset exists foreach (Reloc reloc in relocs) { if (reloc.offset == offset && reloc.type != BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(reloc); virtualSize -= 2; if (relocs.Count % 2 != 0) // align in 32bits { bool isAlignDeleted = false; foreach (Reloc item in relocs) // search if align already exists { if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(item); isAlignDeleted = true; virtualSize -= 2; break; } } if (!isAlignDeleted) // if no align reloc found, add it { Reloc item = new Reloc(); item.offset = 0; item.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(item); virtualSize += 2; } } if (relocs.Count == 0) // remove page if nothing offset { pages.Remove((address & 0xFFFFF000) - imageBase); virtualSize -= 8; } IsNotSaved = true; return true; } } return false; }
/// <summary> /// Add a relocation address /// </summary> /// <param name="address">Address to add</param> /// <param name="type">Type of relocation</param> /// <returns>-1 if duplicated, 0 if not added, 1 if added a page and 2 if added only in reloc of page</returns> public int AddRelocation(uint address, BASE_RELOCATION_TYPE type) { if (address < imageBase) return 0; uint page = (address & 0xFFFFF000) - imageBase; ushort offset = (ushort)(address & 0x00000FFF); if (!pages.ContainsKey(page)) // create a new page if doesn't exists { if (RawSize - virtualSize < 12) return 0; List<Reloc> relocs = new List<Reloc>(); Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); reloc = new Reloc(); reloc.offset = 0; reloc.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(reloc); pages.Add(page, relocs); virtualSize += 12; IsNotSaved = true; return 1; } else // just added the offset { List<Reloc> relocs; if (!pages.TryGetValue(page, out relocs)) return 0; foreach (Reloc item in relocs) // search if address already present { if (item.offset == offset && item.type != BASE_RELOCATION_TYPE.ABSOLUTE) return -1; } if (relocs.Count % 2 == 0) // align in 32bits { bool isAlignDeleted = false; foreach (Reloc item in relocs) // search if align already exists { if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE) { relocs.Remove(item); isAlignDeleted = true; virtualSize -= 2; break; } } if (!isAlignDeleted) // if no align reloc found, add it { if (RawSize - virtualSize < 4) return 0; Reloc item = new Reloc(); item.offset = 0; item.type = BASE_RELOCATION_TYPE.ABSOLUTE; relocs.Add(item); virtualSize += 2; } } Reloc reloc = new Reloc(); reloc.offset = offset; reloc.type = type; relocs.Add(reloc); virtualSize += 2; IsNotSaved = true; return 2; } }