Beispiel #1
0
        private static uint GetSymValue(Elf_Header *aHeader, int aTableIdx, int aSymIdx)
        {
            uint       BaseAddress = (uint)aHeader;
            Elf_Shdr * SymSection  = (Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + aTableIdx;
            Elf32_Sym *SymTab      = (Elf32_Sym *)(SymSection->sh_addr) + aSymIdx;

            switch (SymTab->st_shndx)
            {
            case SHN_UNDEF:
            {
                var    StrTabAdd = ((Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + SymSection->sh_link)->sh_addr;
                string SymName   = new string((sbyte *)(StrTabAdd + SymTab->st_name));

                Debug.Write("Undefined Symbol: %s\n", SymName);
                Heap.Free(SymName);
                throw new Exception("[ELF]: Extern Symbol not supported");
            }

            case SHN_ABS:
                return(SymTab->st_value);

            default:
                Elf_Shdr *TargetSection = (Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + SymTab->st_shndx;
                return(TargetSection->sh_addr + SymTab->st_value);
            }
        }
Beispiel #2
0
        private static void RegisterSymbol(Elf_Header *aHeader, Elf_Shdr *aShdr, string aPath)
        {
            uint       BaseAddress = (uint)aHeader;
            Elf32_Sym *SymTab      = (Elf32_Sym *)aShdr->sh_addr;
            var        StrTabAdd   = ((Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + aShdr->sh_link)->sh_addr;

            uint count = aShdr->sh_size / aShdr->sh_entsize;

            uint Address;

            for (uint i = 0; i < count; i++, SymTab++)
            {
                uint flag = (uint)(SymTab->st_info >> 4);
                if (flag == STB_GLOBAL)
                {
                    switch (SymTab->st_shndx)
                    {
                    case SHN_UNDEF:
                        continue;     // for now ignore UNDEF Symbols

                    case SHN_ABS:
                        Address = SymTab->st_value;
                        break;

                    default:
                        var TargetSection = (Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + SymTab->st_shndx;
                        Address = TargetSection->sh_addr + SymTab->st_value;
                        break;
                    }

                    string SymName = new string((sbyte *)(StrTabAdd + SymTab->st_name));
                    Debug.Write("Symbol: %s\n", SymName);
                }
            }
        }
Beispiel #3
0
        const uint STB_WEAK   = 2;                  /* Weak, (ie. __attribute__((weak))) */

        internal static uint Load(string aPath)
        {
            Stream xStream = VirtualFileSystem.GetFile(aPath);

            if (xStream == null)
            {
                throw new Exception("[ELF]: File not found!");
            }

            var xData = new byte[xStream.FileSize];

            xStream.Read(xData, xData.Length);

            uint        BaseAddress = xData.GetDataOffset();
            Elf_Header *Header      = (Elf_Header *)BaseAddress;

            /* verify ELF header and if this code support this type of elf */
            CheckHeader(Header);

            /* prepare sections and allocate memory (if required) */
            Elf_Shdr *Shdr = (Elf_Shdr *)(BaseAddress + Header->e_shoff);

            for (int i = 0; i < Header->e_shnum; i++, Shdr++)
            {
                Shdr->sh_addr = BaseAddress + Shdr->sh_offset;
                if ((Shdr->sh_flags & SHF_ALLOC) != 0)
                {
                    LoadSection(BaseAddress, Shdr);
                }
            }

            /* Iterate over all sections and perform relocations */
            Shdr = (Elf_Shdr *)(BaseAddress + Header->e_shoff);
            for (int i = 0; i < Header->e_shnum; i++, Shdr++)
            {
                switch (Shdr->sh_type)
                {
                case SHT_SYMTAB:
                {
                    RegisterSymbol(Header, Shdr, aPath);
                }
                break;

                case SHT_REL:
                {
                    Shdr->sh_addr = BaseAddress + Shdr->sh_offset;
                    Relocate(Header, Shdr);
                }
                break;
                }
            }

            uint LoadAddress = Header->e_entry;

            Heap.Free(xData);

            return(LoadAddress);
        }
Beispiel #4
0
        private static void Relocate(Elf_Header *aHeader, Elf_Shdr *aShdr)
        {
            uint       BaseAddress   = (uint)aHeader;
            Elf32_Rel *Reloc         = (Elf32_Rel *)aShdr->sh_addr;
            Elf_Shdr * TargetSection = (Elf_Shdr *)(BaseAddress + aHeader->e_shoff) + aShdr->sh_info;

            uint RelocCount = aShdr->sh_size / aShdr->sh_entsize;

            byte SymIdx;
            uint SymVal, RelocType;

            for (uint i = 0; i < RelocCount; i++, Reloc++)
            {
                SymVal    = 0;
                SymIdx    = (byte)(Reloc->r_info >> 8);
                RelocType = Reloc->r_info & 0xFF;

                if (SymIdx != SHN_UNDEF)
                {
                    if (RelocType == R_386_PLT32)
                    {
                        SymVal = 0;
                    }
                    else
                    {
                        SymVal = GetSymValue(aHeader, TargetSection->sh_link, SymIdx);
                    }
                }

                uint *add_ref = (uint *)(TargetSection->sh_addr + Reloc->r_offset);
                switch (RelocType)
                {
                case R_386_32:
                    *add_ref = SymVal + *add_ref;     // S + A
                    break;

                case R_386_PLT32:       // L + A - P
                case R_386_PC32:        // S + A - P
                default:
                    throw new Exception("[ELF]: Unsupported Relocation type");
                }
            }
        }
Beispiel #5
0
        private static uint LoadSection(uint aBaseAddress, Elf_Shdr *aShdr)
        {
            // make sure address if aligned
            uint align = aShdr->sh_addralign;
            uint addr  = Heap.kmalloc(aShdr->sh_size + align);

            if (align != 0)
            {
                uint offset = addr & (align - 1);
                addr += align - offset;
            }

            if (aShdr->sh_type != SHT_NOBITS)
            {
                Memory.FastCopy(addr, aBaseAddress + aShdr->sh_offset, aShdr->sh_size);
            }

            aShdr->sh_addr = addr;
            return(addr);
        }