/// <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"); }
/// <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; }