Section* XdfObject::AppendSection(llvm::StringRef name, SourceLocation source, Diagnostic& diags) { bool code = (name == ".text"); Section* section = new Section(name, code, false, source); m_object.AppendSection(std::auto_ptr<Section>(section)); // Define a label for the start of the section Location start = {§ion->bytecodes_front(), 0}; SymbolRef sym = m_object.getSymbol(name); if (!sym->isDefined()) { sym->DefineLabel(start); sym->setDefSource(source); } section->setSymbol(sym); // Add XDF data to the section section->AddAssocData(std::auto_ptr<XdfSection>(new XdfSection(sym))); return section; }
void Win64Object::DirEndProcFrame(DirectiveInfo& info, Diagnostic& diags) { assert(info.isObject(m_object)); SourceLocation source = info.getSource(); if (!m_proc_frame.isValid()) { diags.Report(source, diags.getCustomDiagID(Diagnostic::Error, "no preceding [PROC_FRAME]")); return; } if (!m_done_prolog.isValid()) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "ended procedure without ending prologue")); diags.Report(m_proc_frame, diags.getCustomDiagID(Diagnostic::Note, "procedure started here")); m_unwind.reset(0); m_proc_frame = SourceLocation(); return; } assert(m_unwind.get() != 0 && "unwind info not present"); SymbolRef proc_sym = m_unwind->getProc(); SymbolRef curpos = m_object.getSymbol(info.getLocation()); // // Add unwind info to end of .xdata section. // Section* xdata = m_object.FindSection(".xdata"); // Create xdata section if needed. if (!xdata) xdata = AppendSection(".xdata", source, diags); // Get current position in .xdata section. SymbolRef unwindpos = m_object.AddNonTableSymbol("$"); Location unwindpos_loc = {&xdata->bytecodes_back(), xdata->bytecodes_back().getFixedLen()}; unwindpos->DefineLabel(unwindpos_loc); // Get symbol for .xdata as we'll want to reference it with WRT. SymbolRef xdata_sym = xdata->getAssocData<CoffSection>()->m_sym; // Add unwind info. Use line number of start of procedure. Arch& arch = *m_object.getArch(); Generate(m_unwind, *xdata, m_proc_frame, arch, diags); // // Add function lookup to end of .pdata section. // Section* pdata = m_object.FindSection(".pdata"); // Initialize pdata section if needed. if (!pdata) pdata = AppendSection(".pdata", source, diags); // Add function structure to end of .pdata AppendData(*pdata, std::auto_ptr<Expr>(new Expr(proc_sym)), 4, arch, source, diags); AppendData(*pdata, std::auto_ptr<Expr>(new Expr(WRT(curpos, proc_sym))), 4, arch, source, diags); AppendData(*pdata, std::auto_ptr<Expr>(new Expr(WRT(unwindpos, xdata_sym))), 4, arch, source, diags); m_proc_frame = SourceLocation(); m_done_prolog = SourceLocation(); }
bool XdfObject::Read(SourceManager& sm, Diagnostic& diags) { const llvm::MemoryBuffer& in = *sm.getBuffer(sm.getMainFileID()); InputBuffer inbuf(in); inbuf.setLittleEndian(); // Read object header if (inbuf.getReadableSize() < FILEHEAD_SIZE) { diags.Report(SourceLocation(), diag::err_object_header_unreadable); return false; } unsigned long magic = ReadU32(inbuf); if (magic != XDF_MAGIC) { diags.Report(SourceLocation(), diag::err_not_file_type) << "XDF"; return false; } unsigned long scnum = ReadU32(inbuf); unsigned long symnum = ReadU32(inbuf); unsigned long headers_len = ReadU32(inbuf); if (inbuf.getReadableSize() < headers_len) { diags.Report(SourceLocation(), diag::err_xdf_headers_unreadable); return false; } unsigned long section_offset = FILEHEAD_SIZE; unsigned long symtab_offset = section_offset + SECTHEAD_SIZE*scnum; unsigned long strtab_offset = symtab_offset + SYMBOL_SIZE*symnum; ReadString read_string(in, strtab_offset, FILEHEAD_SIZE+headers_len-strtab_offset, diags); // Storage for nrelocs, indexed by section number std::vector<unsigned long> sects_nrelocs; sects_nrelocs.reserve(scnum); // Create sections for (unsigned long i=0; i<scnum; ++i) { // Start with symbol=0 as it's not created yet; updated later. std::auto_ptr<XdfSection> xsect(new XdfSection(SymbolRef(0))); unsigned long name_sym_index; IntNum lma, vma; unsigned long align; bool bss; unsigned long filepos; unsigned long nrelocs; xsect->Read(in, section_offset+SECTHEAD_SIZE*i, &name_sym_index, &lma, &vma, &align, &bss, &filepos, &nrelocs); xsect->scnum = i; // get section name from section symbol entry inbuf.setPosition(symtab_offset+name_sym_index*SYMBOL_SIZE+8); llvm::StringRef sectname = read_string(ReadU32(inbuf)); std::auto_ptr<Section> section( new Section(sectname, xsect->bits != 0, bss, SourceLocation())); section->setFilePos(filepos); section->setVMA(vma); section->setLMA(lma); if (bss) { Bytecode& gap = section->AppendGap(xsect->size, SourceLocation()); Diagnostic nodiags(0); gap.CalcLen(0, nodiags); // force length calculation of gap } else { // Read section data inbuf.setPosition(filepos); if (inbuf.getReadableSize() < xsect->size) { diags.Report(SourceLocation(), diag::err_section_data_unreadable) << sectname; return false; } section->bytecodes_front().getFixed().Write(inbuf.Read(xsect->size), xsect->size); } // Associate section data with section section->AddAssocData(xsect); // Add section to object m_object.AppendSection(section); sects_nrelocs.push_back(nrelocs); } // Create symbols inbuf.setPosition(symtab_offset); for (unsigned long i=0; i<symnum; ++i) { unsigned long sym_scnum = ReadU32(inbuf); // section number unsigned long value = ReadU32(inbuf); // value llvm::StringRef symname = read_string(ReadU32(inbuf));// name unsigned long flags = ReadU32(inbuf); // flags SymbolRef sym = m_object.getSymbol(symname); if ((flags & XdfSymbol::XDF_GLOBAL) != 0) sym->Declare(Symbol::GLOBAL); else if ((flags & XdfSymbol::XDF_EXTERN) != 0) sym->Declare(Symbol::EXTERN); if ((flags & XdfSymbol::XDF_EQU) != 0) sym->DefineEqu(Expr(value)); else if (sym_scnum < scnum) { Section& sect = m_object.getSection(sym_scnum); Location loc = {§.bytecodes_front(), value}; sym->DefineLabel(loc); } // Save index in symrec data sym->AddAssocData(std::auto_ptr<XdfSymbol>(new XdfSymbol(i))); } // Update section symbol info, and create section relocations std::vector<unsigned long>::iterator nrelocsi = sects_nrelocs.begin(); for (Object::section_iterator sect=m_object.sections_begin(), end=m_object.sections_end(); sect != end; ++sect, ++nrelocsi) { XdfSection* xsect = sect->getAssocData<XdfSection>(); assert(xsect != 0); // Read relocations inbuf.setPosition(xsect->relptr); if (inbuf.getReadableSize() < (*nrelocsi) * RELOC_SIZE) { diags.Report(SourceLocation(), diag::err_section_relocs_unreadable) << sect->getName(); return false; } for (unsigned long i=0; i<(*nrelocsi); ++i) { unsigned long addr = ReadU32(inbuf); unsigned long sym_index = ReadU32(inbuf); unsigned long basesym_index = ReadU32(inbuf); XdfReloc::Type type = static_cast<XdfReloc::Type>(ReadU8(inbuf)); XdfReloc::Size size = static_cast<XdfReloc::Size>(ReadU8(inbuf)); unsigned char shift = ReadU8(inbuf); ReadU8(inbuf); // flags; ignored SymbolRef sym = m_object.getSymbol(sym_index); SymbolRef basesym(0); if (type == XdfReloc::XDF_WRT) basesym = m_object.getSymbol(basesym_index); sect->AddReloc(std::auto_ptr<Reloc>( new XdfReloc(addr, sym, basesym, type, size, shift))); } } if (diags.hasErrorOccurred()) return false; return true; }