void Win64Object::DirProcFrame(DirectiveInfo& info, Diagnostic& diags) { assert(info.isObject(m_object)); NameValues& namevals = info.getNameValues(); SourceLocation source = info.getSource(); NameValue& name_nv = namevals.front(); if (!name_nv.isId()) { diags.Report(info.getSource(), diag::err_value_id) << name_nv.getValueRange(); return; } llvm::StringRef name = name_nv.getId(); if (m_proc_frame.isValid()) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "nested procedures not supported (didn't use [ENDPROC_FRAME]?)")); diags.Report(m_proc_frame, diags.getCustomDiagID(Diagnostic::Note, "previous procedure started here")); return; } m_proc_frame = source; m_done_prolog = SourceLocation(); m_unwind.reset(new UnwindInfo); SymbolRef proc = m_object.getSymbol(name); proc->Use(source); m_unwind->setProc(proc); // Optional error handler if (namevals.size() > 1) { NameValue& ehandler_nv = namevals[1]; if (!ehandler_nv.isId()) { diags.Report(info.getSource(), diag::err_value_id) << ehandler_nv.getValueRange(); return; } SymbolRef ehandler = m_object.getSymbol(ehandler_nv.getId()); ehandler->Use(ehandler_nv.getValueRange().getBegin()); m_unwind->setEHandler(ehandler); } }
bool Win64Object::CheckProcFrameState(SourceLocation dir_source, Diagnostic& diags) { if (!m_proc_frame.isValid()) { diags.Report(dir_source, diags.getCustomDiagID(Diagnostic::Error, "no preceding [PROC_FRAME]")); return false; } if (m_done_prolog.isValid()) { diags.Report(dir_source, diags.getCustomDiagID(Diagnostic::Error, "must come before [END_PROLOGUE]")); diags.Report(m_done_prolog, diags.getCustomDiagID(Diagnostic::Note, "prologue ended here")); return false; } return true; }
bool BinObject::setMapFilename(const NameValue& nv, SourceLocation dir_source, Diagnostic& diags) { if (!m_map_filename.empty()) { diags.Report(nv.getValueRange().getBegin(), diags.getCustomDiagID(Diagnostic::Error, "map file already specified")); return true; } if (!nv.isString()) { diags.Report(nv.getValueRange().getBegin(), diag::err_value_string_or_id); return false; } m_map_filename = nv.getString(); return true; }
void BinObject::DirOrg(DirectiveInfo& info, Diagnostic& diags) { // We only allow a single ORG in a program. if (m_org.get() != 0) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "program origin redefined")); return; } // ORG takes just a simple expression as param const NameValue& nv = info.getNameValues().front(); if (!nv.isExpr()) { diags.Report(info.getSource(), diag::err_value_expression) << nv.getValueRange(); return; } m_org.reset(new Expr(nv.getExpr(info.getObject()))); m_org_source = info.getSource(); }
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(); }
void BinObject::DirSection(DirectiveInfo& info, Diagnostic& diags) { assert(info.isObject(m_object)); NameValues& nvs = info.getNameValues(); SourceLocation source = info.getSource(); NameValue& sectname_nv = nvs.front(); if (!sectname_nv.isString()) { diags.Report(sectname_nv.getValueRange().getBegin(), diag::err_value_string_or_id); return; } llvm::StringRef sectname = sectname_nv.getString(); Section* sect = m_object.FindSection(sectname); bool first = true; if (sect) first = sect->isDefault(); else sect = AppendSection(sectname, source, diags); m_object.setCurSection(sect); sect->setDefault(false); // No name/values, so nothing more to do if (nvs.size() <= 1) return; // Ignore flags if we've seen this section before if (!first) { diags.Report(info.getSource(), diag::warn_section_redef_flags); return; } // Parse section flags bool has_follows = false, has_vfollows = false; bool has_start = false, has_vstart = false; std::auto_ptr<Expr> start(0); std::auto_ptr<Expr> vstart(0); BinSection* bsd = sect->getAssocData<BinSection>(); assert(bsd); unsigned long bss = sect->isBSS(); unsigned long code = sect->isCode(); DirHelpers helpers; helpers.Add("follows", true, TR1::bind(&DirString, _1, _2, &bsd->follows, &has_follows)); helpers.Add("vfollows", true, TR1::bind(&DirString, _1, _2, &bsd->vfollows, &has_vfollows)); helpers.Add("start", true, TR1::bind(&DirExpr, _1, _2, &m_object, &start, &has_start)); helpers.Add("vstart", true, TR1::bind(&DirExpr, _1, _2, &m_object, &vstart, &has_vstart)); helpers.Add("align", true, TR1::bind(&DirIntNumPower2, _1, _2, &m_object, &bsd->align, &bsd->has_align)); helpers.Add("valign", true, TR1::bind(&DirIntNumPower2, _1, _2, &m_object, &bsd->valign, &bsd->has_valign)); helpers.Add("nobits", false, TR1::bind(&DirSetFlag, _1, _2, &bss, 1)); helpers.Add("progbits", false, TR1::bind(&DirClearFlag, _1, _2, &bss, 1)); helpers.Add("code", false, TR1::bind(&DirSetFlag, _1, _2, &code, 1)); helpers.Add("data", false, TR1::bind(&DirClearFlag, _1, _2, &code, 1)); helpers.Add("execute", false, TR1::bind(&DirSetFlag, _1, _2, &code, 1)); helpers.Add("noexecute", false, TR1::bind(&DirClearFlag, _1, _2, &code, 1)); helpers(++nvs.begin(), nvs.end(), info.getSource(), diags, DirNameValueWarn); if (start.get() != 0) { bsd->start.reset(start.release()); bsd->start_source = source; } if (vstart.get() != 0) { bsd->vstart.reset(vstart.release()); bsd->vstart_source = source; } if (bsd->start.get() != 0 && !bsd->follows.empty()) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "cannot combine '%0' and '%1' section attributes")) << "START" << "FOLLOWS"; } if (bsd->vstart.get() != 0 && !bsd->vfollows.empty()) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "cannot combine '%0' and '%1' section attributes")) << "VSTART" << "VFOLLOWS"; } sect->setBSS(bss); sect->setCode(code); }
void XdfObject::DirSection(DirectiveInfo& info, Diagnostic& diags) { assert(info.isObject(m_object)); NameValues& nvs = info.getNameValues(); NameValue& sectname_nv = nvs.front(); if (!sectname_nv.isString()) { diags.Report(sectname_nv.getValueRange().getBegin(), diag::err_value_string_or_id); return; } llvm::StringRef sectname = sectname_nv.getString(); Section* sect = m_object.FindSection(sectname); bool first = true; if (sect) first = sect->isDefault(); else sect = AppendSection(sectname, info.getSource(), diags); XdfSection* xsect = sect->getAssocData<XdfSection>(); assert(xsect != 0); m_object.setCurSection(sect); sect->setDefault(false); if (xsect->bits != 0) m_object.getArch()->setVar("mode_bits", xsect->bits); // reapply // No name/values, so nothing more to do if (nvs.size() <= 1) return; // Ignore flags if we've seen this section before if (!first) { diags.Report(info.getSource(), diag::warn_section_redef_flags); return; } // Parse section flags IntNum align; bool has_align = false; unsigned long bss = sect->isBSS(); unsigned long code = sect->isCode(); IntNum vma = sect->getVMA(); IntNum lma = sect->getLMA(); unsigned long flat = xsect->flat; DirHelpers helpers; helpers.Add("use16", false, TR1::bind(&DirResetFlag, _1, _2, &xsect->bits, 16)); helpers.Add("use32", false, TR1::bind(&DirResetFlag, _1, _2, &xsect->bits, 32)); helpers.Add("use64", false, TR1::bind(&DirResetFlag, _1, _2, &xsect->bits, 64)); helpers.Add("bss", false, TR1::bind(&DirSetFlag, _1, _2, &bss, 1)); helpers.Add("nobss", false, TR1::bind(&DirClearFlag, _1, _2, &bss, 1)); helpers.Add("code", false, TR1::bind(&DirSetFlag, _1, _2, &code, 1)); helpers.Add("data", false, TR1::bind(&DirClearFlag, _1, _2, &code, 1)); helpers.Add("flat", false, TR1::bind(&DirSetFlag, _1, _2, &flat, 1)); helpers.Add("noflat", false, TR1::bind(&DirClearFlag, _1, _2, &flat, 1)); helpers.Add("absolute", true, TR1::bind(&DirIntNum, _1, _2, &m_object, &lma, &xsect->has_addr)); helpers.Add("virtual", true, TR1::bind(&DirIntNum, _1, _2, &m_object, &vma, &xsect->has_vaddr)); helpers.Add("align", true, TR1::bind(&DirIntNumPower2, _1, _2, &m_object, &align, &has_align)); helpers(++nvs.begin(), nvs.end(), info.getSource(), diags, DirNameValueWarn); if (has_align) { unsigned long aligni = align.getUInt(); // Check to see if alignment is supported size // FIXME: Use actual value source location if (aligni > 4096) { diags.Report(info.getSource(), diags.getCustomDiagID(Diagnostic::Error, "XDF does not support alignments > 4096")); } sect->setAlign(aligni); } sect->setBSS(bss); sect->setCode(code); sect->setVMA(vma); sect->setLMA(lma); xsect->flat = flat; if (xsect->bits != 0) m_object.getArch()->setVar("mode_bits", xsect->bits); }