Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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();
        }
Example #4
0
        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 });
            }
        }
Example #5
0
        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;
        }