예제 #1
0
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);
}
예제 #2
0
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);
}