Example #1
0
        /// <summary>
        /// Parse the section headers.
        /// </summary>
        private void ParseSectionHdrs()
        {
            UInt32 byteSize, wordSize, numBytesInSectionHdr;
              UInt64 flags;
              ELF_SectionHeader secHdr;
              EndianBinaryReader ebr = new EndianBinaryReader(binFile, endian);

              numBytesInSectionHdr = hdr.e_shentsize;

              Debug.DebugMSG("Parsing ELF Sections Headers");

              if (sectionCount == (UInt32) ELF_SectionIndex.SHN_UNDEF)
              {
            // Get the actual number of sections from the sh_size field of the
            // 0th section header table entry
            secHdr = ReadSectionHeader(0);
            sectionCount = (UInt32) secHdr.sh_size;
            headerRef["numSectionHdrs"] = (UInt32) secHdr.sh_size;
              }

              // Get Section Header String Table Section Header Index and Section Header String Table Section Address
              if (hdr.e_shstrndx == (UInt16) ELF_SectionIndex.SHN_UNDEF)
              {
            headerRef["stringTableAddr"] = null;
            headerRef["stringHeaderTableIndex"] = null;
            secHdr = new ELF_SectionHeader();
              }
              else if (hdr.e_shstrndx == (UInt16) ELF_SectionIndex.SHN_XINDEX)
              {
            secHdr = ReadSectionHeader(0);
            headerRef["stringHeaderTableIndex"] = (UInt32) secHdr.sh_link;
            secHdr = ReadSectionHeader((UInt32) headerRef["stringHeaderTableIndex"]);
            headerRef["stringTableAddr"] = (UInt64) secHdr.sh_addr;
              }
              else
              {
            headerRef["stringHeaderTableIndex"] = (UInt32) hdr.e_shstrndx;
            secHdr = ReadSectionHeader((UInt32) headerRef["stringHeaderTableIndex"]);
            headerRef["stringTableAddr"] = (UInt64) (secHdr.sh_offset);
              }
              Debug.DebugMSG("Section Header Table Index for Section Header String Table: " + (UInt32)headerRef["stringHeaderTableIndex"]);
              Debug.DebugMSG("String Section Start Addr: 0x" + ((UInt64)headerRef["stringTableAddr"]).ToString("X8"));

              // Verify that the section header string table section is flagged as a string section
              flags = (UInt64) secHdr.sh_flags;
              Debug.DebugMSG("secHdr.sh_flags = " + secHdr.sh_flags.ToString());
              if ( ( flags & ((UInt64) ELF_SectionFlag.SHF_STRINGS) ) == 0 )
              {
            Debug.DebugMSG("WARNING: Section Header String Section is not flagged with SHF_STRINGS");
              }
              if (secHdr.sh_type != ELF_SectionType.SHT_STRTAB)
              {
            throw new Exception("Section Header String Section is not of type SHT_STRTAB.");
              }

              if ( hdr.e_phnum == 0x0)
              {
            throw new Exception("Load addresses cannot be calculated without program header.");
              }

              // Cycle through all sections, collecting info about each (name, type, etc.)
              sectionRef  = new Hashtable[sectionCount];
              sections    = new ObjectSection[sectionCount];
              for (UInt32 secNum = 0; secNum < sectionCount; secNum++)
              {
            sectionRef[secNum]  = new Hashtable();
            sections[secNum]    = new ObjectSection();
            secHdr = ReadSectionHeader((UInt32) secNum);

            ebr.BaseStream.Seek((Int64)(secHdr.sh_name + (UInt64)headerRef["stringTableAddr"]), SeekOrigin.Begin);
            sectionRef[secNum]["name"]      = ELF_getStringFromStringTable();
            sectionRef[secNum]["type"]      = (ELF_SectionType) secHdr.sh_type;
            sectionRef[secNum]["phyAddr"]   = (UInt64) secHdr.sh_addr;
            sectionRef[secNum]["virAddr"]   = (UInt64) secHdr.sh_addr;
            sectionRef[secNum]["fileAddr"]  = (UInt64) secHdr.sh_offset;

            byteSize = (UInt32) secHdr.sh_size;
            wordSize = (byteSize + 3) >> 2;
            byteSize = wordSize << 2;
            sectionRef[secNum]["byteSize"]  = byteSize;
            sectionRef[secNum]["wordSize"] = wordSize;
            sectionRef[secNum]["flags"] = (UInt64) secHdr.sh_flags;

            flags = (UInt64) sectionRef[secNum]["flags"];

            // FIXME: Check to see if section should be copied to target
            sectionRef[secNum]["copyToTarget"] = false;
            if ( ( ((UInt64) sectionRef[secNum]["phyAddr"])   != 0 ) &&
             ( ((UInt32) sectionRef[secNum]["byteSize"])  != 0 ) &&
             ( ELF_SectionType.SHT_NULL                   != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_NOBITS                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_SYMTAB                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_DYNSYM                 != (ELF_SectionType)sectionRef[secNum]["type"] ) &&
             ( ELF_SectionType.SHT_STRTAB                 != (ELF_SectionType)sectionRef[secNum]["type"] )             )
            {
              if ( ( ELF_SectionType.SHT_PROGBITS == (ELF_SectionType)sectionRef[secNum]["type"] ) &&
               ( (flags | ((UInt64) ELF_SectionFlag.SHF_ALLOC)) != 0x0 ) )
              {
            headerRef["numTargetSections"] = ((UInt32)headerRef["numTargetSections"]) + 1;
            sectionRef[secNum]["copyToTarget"] = true;
              }
            }

            // If we think this section should be copied to target, make sure it is
            // in a loadable ELF program segment.  If it is, then update physical
            // and virtual addresses. If not, then mark it as such.
            if ((Boolean) sectionRef[secNum]["copyToTarget"])
            {
              Boolean segmentFoundForSection = false;
              for (UInt32 segmentNum = 0; segmentNum < (UInt32)hdr.e_phnum; segmentNum++)
              {
            ELF_SegmentHeader segmentHdr = ReadSegmentHeader((UInt32) segmentNum);

            // If the segment is of load type, check to see if the current section resides in it
            if (segmentHdr.p_type == ELF_SegmentType.PT_LOAD)
            {
              // Check if data is in the file, and if so then check if the section
              // is within this current segment
              if ( ( segmentHdr.p_filesz                         != 0                      ) &&
                   ( segmentHdr.p_vaddr                          <= (UInt64) secHdr.sh_addr) &&
                   ( (segmentHdr.p_vaddr + segmentHdr.p_filesz)  >  (UInt64) secHdr.sh_addr) &&
                   ( segmentHdr.p_offset                         <= (UInt64) secHdr.sh_offset) &&
                   ( (segmentHdr.p_offset + segmentHdr.p_filesz) >  (UInt64) secHdr.sh_offset) )

              {
                sectionRef[secNum]["phyAddr"] = (UInt64) segmentHdr.p_paddr + ( secHdr.sh_addr - segmentHdr.p_vaddr);
                segmentFoundForSection = true;
              }
            }
              }
              if (!segmentFoundForSection)
              {
            // This section is not actually in a loadable ELF program segment, indicate that
            sectionRef[secNum]["copyToTarget"] = false;
              }
            }

            sections[secNum].name         = (String) sectionRef[secNum]["name"];
            sections[secNum].size         = (UInt32) sectionRef[secNum]["byteSize"];
            sections[secNum].runAddr      = (UInt64) sectionRef[secNum]["virAddr"];
            sections[secNum].loadAddr     = (UInt64) sectionRef[secNum]["phyAddr"];
            sections[secNum].isLoadable   = (Boolean) sectionRef[secNum]["copyToTarget"];
            if (sections[secNum].isLoadable)
            {
              loadableSectionCount++;
            }
            sections[secNum].binFileAddr  = (UInt64) sectionRef[secNum]["fileAddr"];

            Debug.DebugMSG("ObjectSection sections[" + secNum + "] = \n{");
            Debug.DebugMSG("\tname = " + sections[secNum].name + ",");
            Debug.DebugMSG("\tsize = " + sections[secNum].size.ToString("X8") + ",");
            Debug.DebugMSG("\trunAddr = " + sections[secNum].runAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tloadAddr = " + sections[secNum].loadAddr.ToString("X8") + ",");
            Debug.DebugMSG("\tisLoadable = " + sections[secNum].isLoadable + ",");
            Debug.DebugMSG("\tbinFileAddr = " + sections[secNum].binFileAddr.ToString("X8"));
            Debug.DebugMSG("}");
              }

              // Fill in the loadableSections array
              loadableSections = new ObjectSection[loadableSectionCount];
              for (UInt32 secNum = 0,loadableSecNum=0; secNum < sectionCount; secNum++)
              {
            if (sections[secNum].isLoadable)
            {
              loadableSections[loadableSecNum] = sections[secNum];
              loadableSecNum++;
            }
              }

              // Finally, sort the loadable sections array by load address
              Array.Sort<ObjectSection>(loadableSections);

              Debug.DebugMSG("Parse Section Headers Done");
        }
Example #2
0
        /// <summary>
        /// Read the section header from the section header table
        /// </summary>
        private ELF_SectionHeader ReadSectionHeader(UInt32 index)
        {
            EndianBinaryReader ebr = new EndianBinaryReader(binFile, endian);
              ELF_SectionHeader sectionHeader = new ELF_SectionHeader();

              // Seek to the start of the section header in section header table
              binFile.Seek((Int64)(hdr.e_shentsize * index + hdr.e_shoff), SeekOrigin.Begin);

              //Debug.DebugMSG( "Header for Section["+index+"] = \n{");

              sectionHeader.sh_name = ebr.ReadUInt32();
              sectionHeader.sh_type = (ELF_SectionType) ebr.ReadUInt32();

              //Debug.DebugMSG(   "  Section Name Index         : " + sectionHeader.sh_name);
              //Debug.DebugMSG(   "  Section Type               : " + sectionHeader.sh_type);

              if (ELF_FileClass.ELFCLASS_32 == hdr.e_ident.fileClass)
              {
            sectionHeader.sh_flags      = (UInt64) ebr.ReadUInt32();
            sectionHeader.sh_addr       = (UInt64) ebr.ReadUInt32();
            sectionHeader.sh_offset     = (UInt64) ebr.ReadUInt32();
            sectionHeader.sh_size       = (UInt64) ebr.ReadUInt32();

            //Debug.DebugMSG( "  Section Flags              : 0x" + sectionHeader.sh_flags.ToString("X8"));
            //Debug.DebugMSG( "  Section Address            : 0x" + sectionHeader.sh_addr.ToString("X8"));
            //Debug.DebugMSG( "  Section Offset             : 0x" + sectionHeader.sh_offset.ToString("X8"));
            //Debug.DebugMSG( "  Section Size               : 0x" + sectionHeader.sh_size.ToString("X8"));
              }
              else
              {
            sectionHeader.sh_flags      = ebr.ReadUInt64();
            sectionHeader.sh_addr       = ebr.ReadUInt64();
            sectionHeader.sh_offset     = ebr.ReadUInt64();
            sectionHeader.sh_size       = ebr.ReadUInt64();

            //Debug.DebugMSG( "  Section Flags              : 0x" + sectionHeader.sh_flags.ToString("X16"));
            //Debug.DebugMSG( "  Section Address            : 0x" + sectionHeader.sh_addr.ToString("X16"));
            //Debug.DebugMSG( "  Section Offset             : 0x" + sectionHeader.sh_offset.ToString("X16"));
            //Debug.DebugMSG( "  Section Size               : 0x" + sectionHeader.sh_size.ToString("X16"));
              }
              sectionHeader.sh_link      = ebr.ReadUInt32();
              sectionHeader.sh_info      = ebr.ReadUInt32();
              //Debug.DebugMSG(   "  Section Link Index         : 0x" + sectionHeader.sh_flags.ToString("X8"));
              //Debug.DebugMSG(   "  Section Info Field         : 0x" + sectionHeader.sh_addr.ToString("X8"));

              if (ELF_FileClass.ELFCLASS_32 == hdr.e_ident.fileClass)
              {
            sectionHeader.sh_addralign      = (UInt64) ebr.ReadUInt32();
            sectionHeader.sh_entsize        = (UInt64) ebr.ReadUInt32();

            //Debug.DebugMSG( "  Section Addr Aligmnent     : 0x" + sectionHeader.sh_addralign.ToString("X8"));
            //Debug.DebugMSG( "  Section Entry Size         : 0x" + sectionHeader.sh_entsize.ToString("X8"));
              }
              else
              {
            sectionHeader.sh_addralign      = ebr.ReadUInt64();
            sectionHeader.sh_entsize        = ebr.ReadUInt64();

            //Debug.DebugMSG( "  Section Addr Aligmnent     : 0x" + sectionHeader.sh_addralign.ToString("X16"));
            //Debug.DebugMSG( "  Section Entry Size         : 0x" + sectionHeader.sh_entsize.ToString("X16"));
              }
              //Debug.DebugMSG("}");

              return sectionHeader;
        }