static void MapPrescanBytes(const Section& sect, const BinSection& bsd, int* bytes) { while (!bsd.length.isOkSize(*bytes * 8, 0, 0)) *bytes *= 2; while (!sect.getLMA().isOkSize(*bytes * 8, 0, 0)) *bytes *= 2; while (!sect.getVMA().isOkSize(*bytes * 8, 0, 0)) *bytes *= 2; }
void CoffSymbol::Write(Bytes& bytes, const Symbol& sym, DiagnosticsEngine& diags, StringTable& strtab) const { int vis = sym.getVisibility(); IntNum value = 0; unsigned int scnum = 0xfffe; // -2 = debugging symbol unsigned long scnlen = 0; // for sect auxent unsigned long nreloc = 0; // for sect auxent // Look at symrec for value/scnum/etc. Location loc; if (sym.getLabel(&loc)) { Section* sect = 0; if (loc.bc) sect = loc.bc->getContainer()->getSection(); // it's a label: get value and offset. // If there is not a section, leave as debugging symbol. if (sect) { CoffSection* coffsect = sect->getAssocData<CoffSection>(); assert(coffsect != 0); scnum = coffsect->m_scnum; scnlen = coffsect->m_size; nreloc = sect->getRelocs().size(); value = sect->getVMA(); if (loc.bc) value += loc.getOffset(); } } else if (const Expr* equ_expr_c = sym.getEqu()) { Expr equ_expr = *equ_expr_c; if (!ExpandEqu(equ_expr)) { diags.Report(sym.getDefSource(), diag::err_equ_circular_reference); return; } SimplifyCalcDist(equ_expr, diags); // trivial case: simple integer if (equ_expr.isIntNum()) { scnum = 0xffff; // -1 = absolute symbol value = equ_expr.getIntNum(); } else { // otherwise might contain relocatable value (e.g. symbol alias) std::auto_ptr<Expr> equ_expr_p(new Expr); equ_expr_p->swap(equ_expr); Value val(64, equ_expr_p); val.setSource(sym.getDefSource()); if (!val.Finalize(diags, diag::err_equ_too_complex)) return; if (val.isComplexRelative()) { diags.Report(sym.getDefSource(), diag::err_equ_too_complex); return; } // set section appropriately based on if value is relative if (val.isRelative()) { SymbolRef rel = val.getRelative(); Location loc; if (!rel->getLabel(&loc) || !loc.bc) { // Referencing an undefined label? // GNU as silently allows this... but doesn't gen the symbol? // We make it an error instead. diags.Report(sym.getDefSource(), diag::err_equ_too_complex); return; } Section* sect = loc.bc->getContainer()->getSection(); CoffSection* coffsect = sect->getAssocData<CoffSection>(); assert(coffsect != 0); scnum = coffsect->m_scnum; value = sect->getVMA() + loc.getOffset(); } else { scnum = 0xffff; // -1 = absolute symbol value = 0; } // add in any remaining absolute portion if (Expr* abs = val.getAbs()) { SimplifyCalcDist(*abs, diags); if (abs->isIntNum()) value += abs->getIntNum(); else diags.Report(sym.getDefSource(), diag::err_equ_not_integer); } } } else { if (vis & Symbol::COMMON) { assert(getCommonSize(sym) != 0); Expr csize(*getCommonSize(sym)); SimplifyCalcDist(csize, diags); if (csize.isIntNum()) value = csize.getIntNum(); else { diags.Report(sym.getDefSource(), diag::err_common_size_not_integer); } scnum = 0; } if (vis & Symbol::EXTERN) scnum = 0; } bytes.setLittleEndian(); StringRef name; if (sym.isAbsoluteSymbol()) name = ".absolut"; else name = sym.getName(); size_t len = name.size(); if (len > 8) { Write32(bytes, 0); // "zeros" field Write32(bytes, strtab.getIndex(name)); // strtab offset } else { // <8 chars, so no string table entry needed bytes.WriteString(name); bytes.Write(8-len, 0); } Write32(bytes, value); // value Write16(bytes, scnum); // section number Write16(bytes, m_type); // type Write8(bytes, m_sclass); // storage class Write8(bytes, m_aux.size()); // number of aux entries assert(bytes.size() == 18); for (std::vector<AuxEntry>::const_iterator i=m_aux.begin(), end=m_aux.end(); i != end; ++i) { switch (m_auxtype) { case AUX_NONE: bytes.Write(18, 0); break; case AUX_SECT: Write32(bytes, scnlen); // section length Write16(bytes, nreloc); // number relocs bytes.Write(12, 0); // number line nums, 0 fill break; case AUX_FILE: len = i->fname.length(); if (len > 18) { Write32(bytes, 0); Write32(bytes, strtab.getIndex(i->fname)); bytes.Write(18-8, 0); } else { bytes.WriteString(i->fname); bytes.Write(18-len, 0); } break; default: assert(false); // unrecognized aux symtab type } } assert(bytes.size() == 18+18*m_aux.size()); }
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); }