public void AddModule(Elf elf) { if (_linked) throw new InvalidOperationException("This linker has already been linked"); if (_modules.Contains(elf)) throw new InvalidOperationException("This module is already part of this linker"); _modules.Add(elf); }
private void ProcessRelaSection(Elf elf, Elf.ElfSection relocs, Elf.ElfSection section, Elf.ElfSection symtab) { if (relocs.sh_entsize != 12) { throw new InvalidDataException("Invalid relocs format (sh_entsize != 12)"); } if (symtab.sh_type != Elf.ElfSection.Type.SHT_SYMTAB) { throw new InvalidDataException("Symbol table does not have type SHT_SYMTAB"); } var reader = new BinaryReader(new MemoryStream(relocs.data)); int count = relocs.data.Length / 12; for (int i = 0; i < count; i++) { uint r_offset = reader.ReadBigUInt32(); uint r_info = reader.ReadBigUInt32(); int r_addend = reader.ReadBigInt32(); Elf.Reloc reloc = (Elf.Reloc)(r_info & 0xFF); int symIndex = (int)(r_info >> 8); if (symIndex == 0) { throw new InvalidDataException("linking to undefined symbol"); } if (!_sectionBases.ContainsKey(section)) { continue; // we don't care about this } string symName = _symbolTableContents[symtab][symIndex]; //Console.WriteLine("{0,-30} {1}", symName, reloc); Word source = _sectionBases[section] + r_offset; Word dest = ResolveSymbol(elf, symName).address + r_addend; //Console.WriteLine("Linking from {0} to {1}", source, dest); if (!KamekUseReloc(reloc, source, dest)) { _fixups.Add(new Fixup { type = reloc, source = source, dest = dest }); } } }
Symbol ResolveSymbol(Elf elf, string name) { var locals = _localSymbols[elf]; if (locals.ContainsKey(name)) { return(locals[name]); } if (_globalSymbols.ContainsKey(name)) { return(_globalSymbols[name]); } if (_externalSymbols.ContainsKey(name)) { return new Symbol { address = new Word(WordType.AbsoluteAddr, _externalSymbols[name]) } } ; throw new InvalidDataException("undefined symbol " + name); }
Symbol ResolveSymbol(Elf elf, string name) { var locals = _localSymbols[elf]; if (locals.ContainsKey(name)) { return(locals[name]); } if (_globalSymbols.ContainsKey(name)) { return(_globalSymbols[name]); } if (_externalSymbols.ContainsKey(name)) { return new Symbol { address = new Word(WordType.AbsoluteAddr, _externalSymbols[name]) } } ; if (name.StartsWith("__kAutoMap_")) { var addr = name.Substring(11); if (addr.StartsWith("0x") || addr.StartsWith("0X")) { addr = addr.Substring(2); } var parsedAddr = uint.Parse(addr, System.Globalization.NumberStyles.AllowHexSpecifier); var mappedAddr = Mapper.Remap(parsedAddr); return(new Symbol { address = new Word(WordType.AbsoluteAddr, mappedAddr) }); } throw new InvalidDataException("undefined symbol " + name); }
Symbol ResolveSymbol(Elf elf, string name) { var locals = _localSymbols[elf]; if (locals.ContainsKey(name)) return locals[name]; if (_globalSymbols.ContainsKey(name)) return _globalSymbols[name]; if (_externalSymbols.ContainsKey(name)) return new Symbol { address = new Word(WordType.AbsoluteAddr, _externalSymbols[name]) }; throw new InvalidDataException("undefined symbol " + name); }
private void ProcessRelaSection(Elf elf, Elf.ElfSection relocs, Elf.ElfSection section, Elf.ElfSection symtab) { if (relocs.sh_entsize != 12) throw new InvalidDataException("Invalid relocs format (sh_entsize != 12)"); if (symtab.sh_type != Elf.ElfSection.Type.SHT_SYMTAB) throw new InvalidDataException("Symbol table does not have type SHT_SYMTAB"); var reader = new BinaryReader(new MemoryStream(relocs.data)); int count = relocs.data.Length / 12; for (int i = 0; i < count; i++) { uint r_offset = reader.ReadBigUInt32(); uint r_info = reader.ReadBigUInt32(); int r_addend = reader.ReadBigInt32(); Elf.Reloc reloc = (Elf.Reloc)(r_info & 0xFF); int symIndex = (int)(r_info >> 8); if (symIndex == 0) throw new InvalidDataException("linking to undefined symbol"); if (!_sectionBases.ContainsKey(section)) continue; // we don't care about this string symName = _symbolTableContents[symtab][symIndex]; //Console.WriteLine("{0,-30} {1}", symName, reloc); Word source = _sectionBases[section] + r_offset; Word dest = ResolveSymbol(elf, symName).address + r_addend; //Console.WriteLine("Linking from {0} to {1}", source, dest); if (!KamekUseReloc(reloc, source, dest)) _fixups.Add(new Fixup { type = reloc, source = source, dest = dest }); } }
private string[] ParseSymbolTable(Elf elf, Elf.ElfSection symtab, Elf.ElfSection strtab, Dictionary<string, Symbol> locals) { if (symtab.sh_entsize != 16) throw new InvalidDataException("Invalid symbol table format (sh_entsize != 16)"); if (strtab.sh_type != Elf.ElfSection.Type.SHT_STRTAB) throw new InvalidDataException("String table does not have type SHT_STRTAB"); var symbolNames = new List<string>(); var reader = new BinaryReader(new MemoryStream(symtab.data)); int count = symtab.data.Length / 16; // always ignore the first symbol symbolNames.Add(null); reader.BaseStream.Seek(16, SeekOrigin.Begin); for (int i = 1; i < count; i++) { // Read info from the ELF uint st_name = reader.ReadBigUInt32(); uint st_value = reader.ReadBigUInt32(); uint st_size = reader.ReadBigUInt32(); byte st_info = reader.ReadByte(); byte st_other = reader.ReadByte(); ushort st_shndx = reader.ReadBigUInt16(); Elf.SymBind bind = (Elf.SymBind)(st_info >> 4); Elf.SymType type = (Elf.SymType)(st_info & 0xF); string name = Util.ExtractNullTerminatedString(strtab.data, (int)st_name); symbolNames.Add(name); if (name.Length == 0 || st_shndx == 0) continue; // What location is this referencing? Elf.ElfSection refSection; if (st_shndx < 0xFF00) refSection = elf.Sections[st_shndx]; else if (st_shndx == 0xFFF1) // absolute symbol refSection = null; else throw new InvalidDataException("unknown section index found in symbol table"); Word addr; if (st_shndx == 0xFFF1) { // Absolute symbol addr = new Word(WordType.AbsoluteAddr, st_value); } else if (st_shndx < 0xFF00) { // Part of a section var section = elf.Sections[st_shndx]; if (!_sectionBases.ContainsKey(section)) continue; // skips past symbols we don't care about, like DWARF junk addr = _sectionBases[section] + st_value; } else throw new NotImplementedException("unknown section index found in symbol table"); switch (bind) { case Elf.SymBind.STB_LOCAL: if (locals.ContainsKey(name)) throw new InvalidDataException("redefinition of local symbol " + name); locals[name] = new Symbol { address = addr, size = st_size }; break; case Elf.SymBind.STB_GLOBAL: if (_globalSymbols.ContainsKey(name) && !_globalSymbols[name].isWeak) throw new InvalidDataException("redefinition of global symbol " + name); _globalSymbols[name] = new Symbol { address = addr, size = st_size }; break; case Elf.SymBind.STB_WEAK: if (!_globalSymbols.ContainsKey(name)) _globalSymbols[name] = new Symbol { address = addr, size = st_size, isWeak = true }; break; } } return symbolNames.ToArray(); }
private bool KamekUseReloc(Elf.Reloc type, Word source, Word dest) { if (source < _kamekStart || source >= _kamekEnd) return false; if (type != Elf.Reloc.R_PPC_ADDR32) return false; _kamekRelocations[source] = dest; return true; }
private string[] ParseSymbolTable(Elf elf, Elf.ElfSection symtab, Elf.ElfSection strtab, Dictionary <string, Symbol> locals) { if (symtab.sh_entsize != 16) { throw new InvalidDataException("Invalid symbol table format (sh_entsize != 16)"); } if (strtab.sh_type != Elf.ElfSection.Type.SHT_STRTAB) { throw new InvalidDataException("String table does not have type SHT_STRTAB"); } var symbolNames = new List <string>(); var reader = new BinaryReader(new MemoryStream(symtab.data)); int count = symtab.data.Length / 16; // always ignore the first symbol symbolNames.Add(null); reader.BaseStream.Seek(16, SeekOrigin.Begin); for (int i = 1; i < count; i++) { // Read info from the ELF uint st_name = reader.ReadBigUInt32(); uint st_value = reader.ReadBigUInt32(); uint st_size = reader.ReadBigUInt32(); byte st_info = reader.ReadByte(); byte st_other = reader.ReadByte(); ushort st_shndx = reader.ReadBigUInt16(); Elf.SymBind bind = (Elf.SymBind)(st_info >> 4); Elf.SymType type = (Elf.SymType)(st_info & 0xF); string name = Util.ExtractNullTerminatedString(strtab.data, (int)st_name); symbolNames.Add(name); if (name.Length == 0 || st_shndx == 0) { continue; } // What location is this referencing? Elf.ElfSection refSection; if (st_shndx < 0xFF00) { refSection = elf.Sections[st_shndx]; } else if (st_shndx == 0xFFF1) // absolute symbol { refSection = null; } else { throw new InvalidDataException("unknown section index found in symbol table"); } Word addr; if (st_shndx == 0xFFF1) { // Absolute symbol addr = new Word(WordType.AbsoluteAddr, st_value); } else if (st_shndx < 0xFF00) { // Part of a section var section = elf.Sections[st_shndx]; if (!_sectionBases.ContainsKey(section)) { continue; // skips past symbols we don't care about, like DWARF junk } addr = _sectionBases[section] + st_value; } else { throw new NotImplementedException("unknown section index found in symbol table"); } switch (bind) { case Elf.SymBind.STB_LOCAL: if (locals.ContainsKey(name)) { throw new InvalidDataException("redefinition of local symbol " + name); } locals[name] = new Symbol { address = addr, size = st_size }; _symbolSizes[addr] = st_size; break; case Elf.SymBind.STB_GLOBAL: if (_globalSymbols.ContainsKey(name) && !_globalSymbols[name].isWeak) { throw new InvalidDataException("redefinition of global symbol " + name); } _globalSymbols[name] = new Symbol { address = addr, size = st_size }; _symbolSizes[addr] = st_size; break; case Elf.SymBind.STB_WEAK: if (!_globalSymbols.ContainsKey(name)) { _globalSymbols[name] = new Symbol { address = addr, size = st_size, isWeak = true }; _symbolSizes[addr] = st_size; } break; } } return(symbolNames.ToArray()); }