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 }; _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()); }