Пример #1
0
void
BinOutput::OutputSection(Section& sect, const IntNum& origin)
{
    BytecodeOutput* outputter;

    if (sect.isBSS())
    {
        outputter = &m_no_output;
    }
    else
    {
        IntNum file_start = sect.getLMA();
        file_start -= origin;
        if (file_start.getSign() < 0)
        {
            Diag(SourceLocation(), diag::err_section_before_origin)
                << sect.getName();
            return;
        }
        if (!file_start.isOkSize(sizeof(unsigned long)*8, 0, 0))
        {
            Diag(SourceLocation(), diag::err_start_too_large)
                << sect.getName();
            return;
        }
        m_fd_os.seek(file_start.getUInt());
        if (m_os.has_error())
        {
            Diag(SourceLocation(), diag::err_file_output_seek);
            return;
        }

        outputter = this;
    }

    for (Section::bc_iterator i=sect.bytecodes_begin(),
         end=sect.bytecodes_end(); i != end; ++i)
    {
        i->Output(*outputter);
    }
}
Пример #2
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);
}
Пример #3
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);
}
Пример #4
0
void
XdfOutput::OutputSection(Section& sect)
{
    BytecodeOutput* outputter = this;

    XdfSection* xsect = sect.getAssocData<XdfSection>();
    assert(xsect != NULL);

    uint64_t pos;
    if (sect.isBSS())
    {
        // Don't output BSS sections.
        outputter = &m_no_output;
        pos = 0;    // position = 0 because it's not in the file
    }
    else
    {
        pos = m_os.tell();
        if (m_os.has_error())
        {
            Diag(SourceLocation(), diag::err_file_output_position);
            return;
        }
    }

    // Output bytecodes
    xsect->size = 0;
    for (Section::bc_iterator i=sect.bytecodes_begin(),
         end=sect.bytecodes_end(); i != end; ++i)
    {
        if (i->Output(*outputter))
            xsect->size += i->getTotalLen();
    }

    // Sanity check final section size
    assert(xsect->size == sect.bytecodes_back().getNextOffset());

    // Empty?  Go on to next section
    if (xsect->size == 0)
        return;

    sect.setFilePos(static_cast<unsigned long>(pos));

    // No relocations to output?  Go on to next section
    if (sect.getRelocs().size() == 0)
        return;

    pos = m_os.tell();
    if (m_os.has_error())
    {
        Diag(SourceLocation(), diag::err_file_output_position);
        return;
    }
    xsect->relptr = static_cast<unsigned long>(pos);

    for (Section::const_reloc_iterator i=sect.relocs_begin(),
         end=sect.relocs_end(); i != end; ++i)
    {
        const XdfReloc& reloc = static_cast<const XdfReloc&>(*i);
        Bytes& scratch = getScratch();
        reloc.Write(scratch);
        assert(scratch.size() == RELOC_SIZE);
        m_os << scratch;
    }
}