static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { const coff_symbol *Symb = Obj.getCOFFSymbol(I); // OK, this is COFF. symbol_iterator SymI(I); StringRef Name; if (error(SymI->getName(Name))) return '?'; char Ret = StringSwitch<char>(Name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); if (Ret != '?') return Ret; uint32_t Characteristics = 0; if (Symb->SectionNumber > 0) { section_iterator SecI = Obj.section_end(); if (error(SymI->getSection(SecI))) return '?'; const coff_section *Section = Obj.getCOFFSection(SecI); Characteristics = Section->Characteristics; } switch (Symb->SectionNumber) { case COFF::IMAGE_SYM_DEBUG: return 'n'; default: // Check section type. if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) return 't'; else if (Characteristics & COFF::IMAGE_SCN_MEM_READ && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. return 'r'; else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) return 'd'; else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) return 'b'; else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) return 'i'; // Check for section symbol. else if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Symb->Value == 0) return 's'; } return '?'; }
error_or<uint64_t> image_entry_coff(const COFFObjectFile& obj) { if (obj.getBytesInAddress() == 4) { const pe32_header* hdr = 0; if (error_code ec = obj.getPE32Header(hdr)) return failure(ec.message()); if (!hdr) return failure("PE header not found"); return error_or<uint64_t>(hdr->AddressOfEntryPoint + hdr->ImageBase); } else { const pe32plus_header *hdr = 0; if (error_code ec = obj.getPE32PlusHeader(hdr)) return failure(ec.message()); if (!hdr) return failure("PE+ header not found"); return error_or<uint64_t>(hdr->AddressOfEntryPoint + hdr->ImageBase); } }
void Decoder::dumpProcedureData(const COFFObjectFile &COFF, const SectionRef Section) { ArrayRef<uint8_t> Contents; if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) return; if (Contents.size() % PDataEntrySize) { errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n"; return; } for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI) if (!dumpProcedureDataEntry(COFF, Section, EI, Contents)) break; }
PDBContext::PDBContext(const COFFObjectFile &Object, std::unique_ptr<IPDBSession> PDBSession) : DIContext(CK_PDB), Session(std::move(PDBSession)) { ErrorOr<uint64_t> ImageBase = Object.getImageBase(); if (ImageBase) Session->setLoadAddress(ImageBase.get()); }
static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); // OK, this is COFF. symbol_iterator SymI(I); ErrorOr<StringRef> Name = SymI->getName(); if (error(Name.getError())) return '?'; char Ret = StringSwitch<char>(*Name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); if (Ret != '?') return Ret; uint32_t Characteristics = 0; if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { ErrorOr<section_iterator> SecIOrErr = SymI->getSection(); if (error(SecIOrErr.getError())) return '?'; section_iterator SecI = *SecIOrErr; const coff_section *Section = Obj.getCOFFSection(*SecI); Characteristics = Section->Characteristics; } switch (Symb.getSectionNumber()) { case COFF::IMAGE_SYM_DEBUG: return 'n'; default: // Check section type. if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) return 't'; if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r'; if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) return 'b'; if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) return 'i'; // Check for section symbol. if (Symb.isSectionDefinition()) return 's'; } return '?'; }
std::vector<segment> read(const COFFObjectFile& obj) { std::vector<segment> segments; const pe32_header *pe32; if (error_code err = obj.getPE32Header(pe32)) llvm_binary_fail(err); for (auto it = obj.begin_sections(); it != obj.end_sections(); ++it) { const coff_section *s = obj.getCOFFSection(it); uint32_t c = static_cast<uint32_t>(s->Characteristics); if ( c & COFF::IMAGE_SCN_CNT_CODE || c & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA || c & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA ) segments.push_back(segment(*pe32, *s)); } return segments; }
PDBContext::PDBContext(const COFFObjectFile &Object, std::unique_ptr<IPDBSession> PDBSession) : DIContext(CK_PDB), Session(std::move(PDBSession)) { uint64_t ImageBase = 0; if (Object.is64()) { const pe32plus_header *Header = nullptr; Object.getPE32PlusHeader(Header); if (Header) ImageBase = Header->ImageBase; } else { const pe32_header *Header = nullptr; Object.getPE32Header(Header); if (Header) ImageBase = static_cast<uint64_t>(Header->ImageBase); } Session->setLoadAddress(ImageBase); }
uint64_t image_entry(const COFFObjectFile& obj) { if (obj.getBytesInAddress() == 4) { const pe32_header* hdr = 0; if (error_code ec = obj.getPE32Header(hdr)) llvm_binary_fail(ec); if (!hdr) llvm_binary_fail("PE header not found"); return hdr->AddressOfEntryPoint; } else { // llvm version 3.4 doesn't support pe32plus_header, // but in version 3.5 it does. So, later one will be // able to write obj->getPE32PlusHeader(hdr) for 64-bit files. uint64_t cur_ptr = 0; const char * buf = (obj.getData()).data(); const uint8_t *start = reinterpret_cast<const uint8_t *>(buf); uint8_t b0 = start[0]; uint8_t b1 = start[1]; if (b0 == 0x4d && b1 == 0x5a) { // Check if this is a PE/COFF file. // A pointer at offset 0x3C points to the PE header. cur_ptr += *reinterpret_cast<const uint16_t *>(start + 0x3c); // Check the PE magic bytes. if (std::memcmp(start + cur_ptr, "PE\0\0", 4) != 0) llvm_binary_fail("PE header not found"); cur_ptr += 4; // Skip the PE magic bytes. cur_ptr += sizeof(coff_file_header); const pe32plus_header *hdr = reinterpret_cast<const pe32plus_header *>(start + cur_ptr); if (hdr->Magic == 0x20b) return hdr->AddressOfEntryPoint; else llvm_binary_fail("PEplus header not found"); } else { llvm_binary_fail("PEplus header not found"); } } };
std::vector<symbol> read(const COFFObjectFile& obj) { std::vector<symbol> symbols; const pe32_header *pe32; if (error_code err = obj.getPE32Header(pe32)) llvm_binary_fail(err); for (auto it = obj.begin_symbols(); it != obj.end_symbols(); ++it) { auto sym = obj.getCOFFSymbol(it); if (!sym) llvm_binary_fail("not a coff symbol"); const coff_section *sec = nullptr; if (sym->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) continue; if (error_code ec = obj.getSection(sym->SectionNumber, sec)) llvm_binary_fail(ec); if (!sec) continue; uint64_t size = (sec->VirtualAddress + sec->SizeOfRawData) - sym->Value; for (auto it = obj.begin_symbols(); it != obj.end_symbols(); ++it) { auto next = obj.getCOFFSymbol(it); if (next->SectionNumber == sym->SectionNumber) { auto new_size = next->Value > sym->Value ? next->Value - sym->Value : size; size = new_size < size ? new_size : size; } } auto addr = sec->VirtualAddress + pe32->ImageBase + sym->Value; symbols.push_back(symbol(*it,addr,size)); } return symbols; }
bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, const SectionRef Section, uint64_t Offset, unsigned Index, const RuntimeFunction &RF) { assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked && "packed entry cannot be treated as an unpacked entry"); ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset); if (!Function) Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true); ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4); if (!XDataRecord) XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA()); if (!RF.BeginAddress && !Function) return false; if (!RF.UnwindData && !XDataRecord) return false; StringRef FunctionName; uint64_t FunctionAddress; if (Function) { Function->getName(FunctionName); Function->getAddress(FunctionAddress); } else { const pe32_header *PEHeader; if (COFF.getPE32Header(PEHeader)) return false; FunctionAddress = PEHeader->ImageBase + RF.BeginAddress; } SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); if (XDataRecord) { StringRef Name; uint64_t Address; XDataRecord->getName(Name); XDataRecord->getAddress(Address); SW.printString("ExceptionRecord", formatSymbol(Name, Address)); section_iterator SI = COFF.section_end(); if (XDataRecord->getSection(SI)) return false; return dumpXDataRecord(COFF, *SI, FunctionAddress, Address); } else { const pe32_header *PEHeader; if (COFF.getPE32Header(PEHeader)) return false; uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA(); SW.printString("ExceptionRecord", formatSymbol("", Address)); ErrorOr<SectionRef> Section = getSectionContaining(COFF, RF.ExceptionInformationRVA()); if (!Section) return false; return dumpXDataRecord(COFF, *Section, FunctionAddress, RF.ExceptionInformationRVA()); } }
bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, const SectionRef &Section, uint64_t FunctionAddress, uint64_t VA) { ArrayRef<uint8_t> Contents; if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) return false; uint64_t SectionVA = Section.getAddress(); uint64_t Offset = VA - SectionVA; const ulittle32_t *Data = reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); const ExceptionDataRecord XData(Data); DictScope XRS(SW, "ExceptionData"); SW.printNumber("FunctionLength", XData.FunctionLength() << 1); SW.printNumber("Version", XData.Vers()); SW.printBoolean("ExceptionData", XData.X()); SW.printBoolean("EpiloguePacked", XData.E()); SW.printBoolean("Fragment", XData.F()); SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes", XData.EpilogueCount()); SW.printNumber("ByteCodeLength", static_cast<uint64_t>(XData.CodeWords() * sizeof(uint32_t))); if (XData.E()) { ArrayRef<uint8_t> UC = XData.UnwindByteCode(); if (!XData.F()) { ListScope PS(SW, "Prologue"); decodeOpcodes(UC, 0, /*Prologue=*/true); } if (XData.EpilogueCount()) { ListScope ES(SW, "Epilogue"); decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false); } } else { ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes(); ListScope ESS(SW, "EpilogueScopes"); for (const EpilogueScope ES : EpilogueScopes) { DictScope ESES(SW, "EpilogueScope"); SW.printNumber("StartOffset", ES.EpilogueStartOffset()); SW.printNumber("Condition", ES.Condition()); SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex()); ListScope Opcodes(SW, "Opcodes"); decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(), /*Prologue=*/false); } } if (XData.X()) { const uint32_t Address = XData.ExceptionHandlerRVA(); const uint32_t Parameter = XData.ExceptionHandlerParameter(); const size_t HandlerOffset = HeaderWords(XData) + (XData.E() ? 0 : XData.EpilogueCount()) + XData.CodeWords(); ErrorOr<SymbolRef> Symbol = getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t)); if (!Symbol) Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true); StringRef Name; if (Symbol) Symbol->getName(Name); ListScope EHS(SW, "ExceptionHandler"); SW.printString("Routine", formatSymbol(Name, Address)); SW.printHex("Parameter", Parameter); } return true; }
static error_code getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I, char &Result) { const coff_symbol *symb = Obj.getCOFFSymbol(I); StringRef name; if (error_code ec = I->getName(name)) return ec; char ret = StringSwitch<char>(name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); if (ret != '?') { Result = ret; return object_error::success; } uint32_t Characteristics = 0; if (symb->SectionNumber > 0) { section_iterator SecI = Obj.end_sections(); if (error_code ec = I->getSection(SecI)) return ec; const coff_section *Section = Obj.getCOFFSection(SecI); Characteristics = Section->Characteristics; } switch (symb->SectionNumber) { case COFF::IMAGE_SYM_UNDEFINED: // Check storage classes. if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) { Result = 'w'; return object_error::success; // Don't do ::toupper. } else if (symb->Value != 0) // Check for common symbols. ret = 'c'; else ret = 'u'; break; case COFF::IMAGE_SYM_ABSOLUTE: ret = 'a'; break; case COFF::IMAGE_SYM_DEBUG: ret = 'n'; break; default: // Check section type. if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) ret = 't'; else if (Characteristics & COFF::IMAGE_SCN_MEM_READ && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. ret = 'r'; else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) ret = 'd'; else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ret = 'b'; else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) ret = 'i'; // Check for section symbol. else if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && symb->Value == 0) ret = 's'; } if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) ret = ::toupper(static_cast<unsigned char>(ret)); Result = ret; return object_error::success; }