DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const { Reg = Reg->StripCasts(); // Look up the dynamic type in the GDM. const DynamicTypeInfo *GDMType = get<DynamicTypeMap>(Reg); if (GDMType) return *GDMType; // Otherwise, fall back to what we know about the region. if (const TypedRegion *TR = dyn_cast<TypedRegion>(Reg)) return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false); if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) { SymbolRef Sym = SR->getSymbol(); return DynamicTypeInfo(Sym->getType()); } return DynamicTypeInfo(); }
static std::error_code resolveRelocation(const Dumper::Context &Ctx, const coff_section *Section, uint64_t Offset, const coff_section *&ResolvedSection, uint64_t &ResolvedAddress) { SymbolRef Symbol; if (std::error_code EC = Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData)) return EC; ErrorOr<uint64_t> ResolvedAddressOrErr = Symbol.getAddress(); if (std::error_code EC = ResolvedAddressOrErr.getError()) return EC; ResolvedAddress = *ResolvedAddressOrErr; ErrorOr<section_iterator> SI = Symbol.getSection(); ResolvedSection = Ctx.COFF.getCOFFSection(**SI); return std::error_code(); }
error_or<int64_t> symbol_address(const ELFObjectFile<T> &obj, const SymbolRef &sym) { auto sym_elf = obj.getSymbol(sym.getRawDataRefImpl()); if (is_rel(obj) && !is_abs_symbol(*sym_elf)) { // abs symbols does not affected by relocations return success(int64_t(0)); } else { auto addr = prim::symbol_address(sym); if (!addr) return addr; auto base = base_address(obj); return success(prim::relative_address(base, *addr)); } }
void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress( const SymbolRef &SymRef, uint64_t Addr) { Elf_Sym *sym = const_cast<Elf_Sym*>( ELFObjectFile<target_endianness, is64Bits>:: getSymbol(SymRef.getRawDataRefImpl())); // This assumes the address passed in matches the target address bitness // The template-based type cast handles everything else. sym->st_value = static_cast<addr_type>(Addr); }
ConditionTruthVal ConstraintManager::checkNull(ProgramStateRef State, SymbolRef Sym) { QualType Ty = Sym->getType(); DefinedSVal V = Loc::isLocType(Ty) ? getLocFromSymbol(State, Sym) : nonloc::SymbolVal(Sym); const ProgramStatePair &P = assumeDual(State, V); if (P.first && !P.second) return ConditionTruthVal(false); if (!P.first && P.second) return ConditionTruthVal(true); return ConditionTruthVal(); }
static std::string formatSymbol(const Dumper::Context &Ctx, const coff_section *Section, uint64_t Offset, uint32_t Displacement) { std::string Buffer; raw_string_ostream OS(Buffer); SymbolRef Symbol; if (!Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData)) { if (ErrorOr<StringRef> Name = Symbol.getName()) { OS << *Name; if (Displacement > 0) OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset); else OS << format(" (0x%" PRIX64 ")", Offset); return OS.str(); } } OS << format(" (0x%" PRIX64 ")", Offset); return OS.str(); }
std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize, DataExtractor *OpdExtractor, uint64_t OpdAddress) { ErrorOr<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType(); if (auto EC = SymbolTypeOrErr.getError()) return EC; SymbolRef::Type SymbolType = *SymbolTypeOrErr; if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) return std::error_code(); ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress(); if (auto EC = SymbolAddressOrErr.getError()) return EC; uint64_t SymbolAddress = *SymbolAddressOrErr; if (OpdExtractor) { // For big-endian PowerPC64 ELF, symbols in the .opd section refer to // function descriptors. The first word of the descriptor is a pointer to // the function's code. // For the purposes of symbolization, pretend the symbol's address is that // of the function's code, not the descriptor. uint64_t OpdOffset = SymbolAddress - OpdAddress; uint32_t OpdOffset32 = OpdOffset; if (OpdOffset == OpdOffset32 && OpdExtractor->isValidOffsetForAddress(OpdOffset32)) SymbolAddress = OpdExtractor->getAddress(&OpdOffset32); } Expected<StringRef> SymbolNameOrErr = Symbol.getName(); if (!SymbolNameOrErr) return errorToErrorCode(SymbolNameOrErr.takeError()); StringRef SymbolName = *SymbolNameOrErr; // Mach-O symbol table names have leading underscore, skip it. if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_') SymbolName = SymbolName.drop_front(); // FIXME: If a function has alias, there are two entries in symbol table // with same address size. Make sure we choose the correct one. auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; SymbolDesc SD = { SymbolAddress, SymbolSize }; M.insert(std::make_pair(SD, SymbolName)); return std::error_code(); }
explicit symbol(const SymbolRef& sym) { StringRef name; if(error_code err = sym.getName(name)) llvm_binary_fail(err); this->name_ = name.str(); if (error_code err = sym.getType(this->kind_)) llvm_binary_fail(err); if (error_code err = sym.getAddress(this->addr_)) llvm_binary_fail(err); if (error_code err = sym.getSize(this->size_)) llvm_binary_fail(err); uint32_t flags; if (error_code err = sym.getFlags(flags)) llvm_binary_fail(err); if (flags & SymbolRef::SF_Undefined) { uint64_t addr; if (error_code err = sym.getValue(addr)) llvm_binary_fail(err); // This will not work for x86-64, since they usually zero // the value. BFD library uses index correspondence // between plt entry and relocation, to name the plt // entry. We can't afford this. if (addr) { addr_ = addr; size_ = 8; } } }
void symbol_entry(const ELFObjectFile<T> &obj, const SymbolRef &sym, ogre_doc &s) { auto sym_elf = obj.getSymbol(sym.getRawDataRefImpl()); if (is_abs_symbol(*sym_elf)) { return; } auto name = prim::symbol_name(sym); auto addr = symbol_address(obj, sym); auto off = symbol_file_offset(obj, sym); if (name && addr && off) { s.entry("symbol-entry") << *name << *addr << sym_elf->st_size << *off; if (sym_elf->getType() == ELF::STT_FUNC) s.entry("code-entry") << *name << *off << sym_elf->st_size ; } }
bool ElfConfig::ReadSymbolTable(const MemoryBuffer& in, const ElfSection& symtab_sect, ElfSymtab& symtab, Object& object, const StringTable& strtab, Section* sections[], DiagnosticsEngine& diags) const { ElfSize symsize = symtab_sect.getEntSize(); if (symsize == 0) { diags.Report(SourceLocation(), diag::err_symbol_entity_size_zero); return false; } unsigned long size = symtab_sect.getSize().getUInt(); // Symbol table always starts with null entry symtab.push_back(SymbolRef(0)); ElfSymbolIndex index = 1; for (unsigned long pos=symsize; pos<size; pos += symsize, ++index) { std::auto_ptr<ElfSymbol> elfsym( new ElfSymbol(*this, in, symtab_sect, index, sections, diags)); if (diags.hasErrorOccurred()) return false; SymbolRef sym = elfsym->CreateSymbol(object, strtab); symtab.push_back(sym); if (sym) sym->AddAssocData(elfsym); // Associate symbol data with symbol } return true; }
bool SymbolReaper::isLive(SymbolRef sym) { if (TheLiving.count(sym)) { markDependentsLive(sym); return true; } bool KnownLive; switch (sym->getKind()) { case SymExpr::RegionValueKind: // FIXME: We should be able to use isLiveRegion here (this behavior // predates isLiveRegion), but doing so causes test failures. Investigate. KnownLive = true; break; case SymExpr::ConjuredKind: KnownLive = false; break; case SymExpr::DerivedKind: KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol()); break; case SymExpr::ExtentKind: KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion()); break; case SymExpr::MetadataKind: KnownLive = MetadataInUse.count(sym) && isLiveRegion(cast<SymbolMetadata>(sym)->getRegion()); if (KnownLive) MetadataInUse.erase(sym); break; case SymExpr::SymIntKind: KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS()); break; case SymExpr::IntSymKind: KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS()); break; case SymExpr::SymSymKind: KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) && isLive(cast<SymSymExpr>(sym)->getRHS()); break; case SymExpr::CastSymbolKind: KnownLive = isLive(cast<SymbolCast>(sym)->getOperand()); break; } if (KnownLive) markLive(sym); return KnownLive; }
static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) { uint64_t Address; if (std::error_code EC = Sym.getAddress(Address)) return EC; if (Address == UnknownAddressOrSize) { Result = UnknownAddressOrSize; return object_error::success; } const ObjectFile *Obj = Sym.getObject(); section_iterator SecI(Obj->section_begin()); if (std::error_code EC = Sym.getSection(SecI)) return EC; if (SecI == Obj->section_end()) { Result = UnknownAddressOrSize; return object_error::success; } uint64_t SectionAddress = SecI->getAddress(); Result = Address - SectionAddress; return object_error::success; }
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; }
ProgramStateRef SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State, SymbolRef Sym, bool Assumption) { BasicValueFactory &BVF = getBasicVals(); QualType T = Sym->getType(); // None of the constraint solvers currently support non-integer types. if (!T->isIntegralOrEnumerationType()) return State; const llvm::APSInt &zero = BVF.getValue(0, T); if (Assumption) return assumeSymNE(State, Sym, zero, zero); else return assumeSymEQ(State, Sym, zero, zero); }
bool SymbolReaper::isLive(SymbolRef sym) { if (TheLiving.count(sym)) { markDependentsLive(sym); return true; } bool KnownLive; switch (sym->getKind()) { case SymExpr::RegionValueKind: KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion()); break; case SymExpr::ConjuredKind: KnownLive = false; break; case SymExpr::DerivedKind: KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol()); break; case SymExpr::ExtentKind: KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion()); break; case SymExpr::MetadataKind: KnownLive = MetadataInUse.count(sym) && isLiveRegion(cast<SymbolMetadata>(sym)->getRegion()); if (KnownLive) MetadataInUse.erase(sym); break; case SymExpr::SymIntKind: KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS()); break; case SymExpr::IntSymKind: KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS()); break; case SymExpr::SymSymKind: KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) && isLive(cast<SymSymExpr>(sym)->getRHS()); break; case SymExpr::CastSymbolKind: KnownLive = isLive(cast<SymbolCast>(sym)->getOperand()); break; } if (KnownLive) markLive(sym); return KnownLive; }
ProgramStateRef RangedConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, bool Assumption) { BasicValueFactory &BVF = getBasicVals(); QualType T = Sym->getType(); // Non-integer types are not supported. if (!T->isIntegralOrEnumerationType()) return State; // Reverse the operation and add directly to state. const llvm::APSInt &Zero = BVF.getValue(0, T); if (Assumption) return assumeSymNE(State, Sym, Zero, Zero); else return assumeSymEQ(State, Sym, Zero, Zero); }
RangeSet RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) { if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym)) return *V; // Lazily generate a new RangeSet representing all possible values for the // given symbol type. BasicValueFactory &BV = getBasicVals(); QualType T = sym->getType(); RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T)); // Special case: references are known to be non-zero. if (T->isReferenceType()) { APSIntType IntType = BV.getAPSIntType(T); Result = Result.Intersect(BV, F, ++IntType.getZeroValue(), --IntType.getZeroValue()); } return Result; }
ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State, SymbolRef Sym) { const RangeSet *Ranges = State->get<ConstraintRange>(Sym); // If we don't have any information about this symbol, it's underconstrained. if (!Ranges) return ConditionTruthVal(); // If we have a concrete value, see if it's zero. if (const llvm::APSInt *Value = Ranges->getConcreteValue()) return *Value == 0; BasicValueFactory &BV = getBasicVals(); APSIntType IntType = BV.getAPSIntType(Sym->getType()); llvm::APSInt Zero = IntType.getZeroValue(); // Check if zero is in the set of possible values. if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty()) return false; // Zero is a possible value, but it is not the /only/ possible value. return ConditionTruthVal(); }
void ElfSymbol::Finalize(Symbol& sym, Diagnostic& diags) { // If symbol is a weakrefr, make it weak at this point. if (m_weak_refr) { if (!sym.isDefined() && (sym.getVisibility() & (Symbol::GLOBAL | Symbol::COMMON)) == 0) { if (sym.isUsed()) { setInTable(true); sym.Declare(Symbol::GLOBAL); setBinding(STB_WEAK); } else { setInTable(false); return; } } else if (!sym.isDefined() && (sym.getVisibility() & Symbol::GLOBAL) != 0) { setBinding(STB_GLOBAL); } } // Don't put the LHS of weakrefs into the symbol table unless they're // specifically requested. if (m_weak_ref && (sym.getVisibility() == Symbol::DLOCAL || sym.getVisibility() == Symbol::LOCAL)) { setInTable(false); return; } // If symbol is in a TLS section, force its type to TLS. Location loc; Section* sect; ElfSection* elfsect; if (sym.getLabel(&loc) && (sect = loc.bc->getContainer()->AsSection()) && (elfsect = sect->getAssocData<ElfSection>()) && (elfsect->getFlags() & SHF_TLS)) { m_type = STT_TLS; } // get size (if specified); expr overrides stored integer if (!m_size.isEmpty()) { if (!ExpandEqu(m_size)) { diags.Report(m_size_source, diag::err_equ_circular_reference); return; } SimplifyCalcDist(m_size, diags); if (!m_size.isIntNum()) diags.Report(m_size_source, diag::err_size_integer); } // get EQU value for constants const Expr* equ_expr_c = sym.getEqu(); if (equ_expr_c != 0) { 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()) { m_index = SHN_ABS; m_value = equ_expr.getIntNum(); return; } // 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? Don't gen the symbol. diags.Report(sym.getDefSource(), diag::warn_equ_undef_ref); m_in_table = false; return; } m_sect = loc.bc->getContainer()->AsSection(); m_value = loc.getOffset(); m_value_rel = rel; } else { m_index = SHN_ABS; m_value = 0; } // add in any remaining absolute portion if (Expr* abs = val.getAbs()) { SimplifyCalcDist(*abs, diags); if (!abs->isIntNum()) { diags.Report(sym.getDefSource(), diag::err_equ_not_integer); return; } m_value += abs->getIntNum(); } } }
error_or<uint64_t> get_addr(const SymbolRef &sym, const COFFObjectFile &obj) { auto er_addr = sym.getAddress(); return of_llvm_error_or(er_addr); }
error_or<std::string> get_name(const SymbolRef &sym) { auto er_name = sym.getName(); auto e = of_llvm_error_or(er_name); return map_value<std::string>(e, [](const StringRef &x){return x.str();}); }
COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { return getCOFFSymbol(Symbol.getRawDataRefImpl()); }
unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); return Symb.getSectionNumber(); }
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(); }
error_or<kind_type> get_kind(const SymbolRef &sym) { auto er_type = sym.getType(); return success(er_type); }
SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) { // Handle trivial case where left-side and right-side are the same. if (lhs == rhs) switch (op) { default: break; case BO_EQ: case BO_LE: case BO_GE: return makeTruthVal(true, resultTy); case BO_LT: case BO_GT: case BO_NE: return makeTruthVal(false, resultTy); case BO_Xor: case BO_Sub: return makeIntVal(0, resultTy); case BO_Or: case BO_And: return evalCastFromNonLoc(lhs, resultTy); } while (1) { switch (lhs.getSubKind()) { default: return generateUnknownVal(state, op, lhs, rhs, resultTy); case nonloc::LocAsIntegerKind: { Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc(); switch (rhs.getSubKind()) { case nonloc::LocAsIntegerKind: return evalBinOpLL(state, op, lhsL, cast<nonloc::LocAsInteger>(rhs).getLoc(), resultTy); case nonloc::ConcreteIntKind: { // Transform the integer into a location and compare. llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue(); i.setIsUnsigned(true); i = i.extOrTrunc(Context.getTypeSize(Context.VoidPtrTy)); return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy); } default: switch (op) { case BO_EQ: return makeTruthVal(false, resultTy); case BO_NE: return makeTruthVal(true, resultTy); default: // This case also handles pointer arithmetic. return generateUnknownVal(state, op, lhs, rhs, resultTy); } } } case nonloc::SymExprValKind: { nonloc::SymExprVal *selhs = cast<nonloc::SymExprVal>(&lhs); // Only handle LHS of the form "$sym op constant", at least for now. const SymIntExpr *symIntExpr = dyn_cast<SymIntExpr>(selhs->getSymbolicExpression()); if (!symIntExpr) return generateUnknownVal(state, op, lhs, rhs, resultTy); // Is this a logical not? (!x is represented as x == 0.) if (op == BO_EQ && rhs.isZeroConstant()) { // We know how to negate certain expressions. Simplify them here. BinaryOperator::Opcode opc = symIntExpr->getOpcode(); switch (opc) { default: // We don't know how to negate this operation. // Just handle it as if it were a normal comparison to 0. break; case BO_LAnd: case BO_LOr: llvm_unreachable("Logical operators handled by branching logic."); case BO_Assign: case BO_MulAssign: case BO_DivAssign: case BO_RemAssign: case BO_AddAssign: case BO_SubAssign: case BO_ShlAssign: case BO_ShrAssign: case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: case BO_Comma: llvm_unreachable("'=' and ',' operators handled by ExprEngine."); case BO_PtrMemD: case BO_PtrMemI: llvm_unreachable("Pointer arithmetic not handled here."); case BO_LT: case BO_GT: case BO_LE: case BO_GE: case BO_EQ: case BO_NE: // Negate the comparison and make a value. opc = NegateComparison(opc); assert(symIntExpr->getType(Context) == resultTy); return makeNonLoc(symIntExpr->getLHS(), opc, symIntExpr->getRHS(), resultTy); } } // For now, only handle expressions whose RHS is a constant. const nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs); if (!rhsInt) return generateUnknownVal(state, op, lhs, rhs, resultTy); // If both the LHS and the current expression are additive, // fold their constants. if (BinaryOperator::isAdditiveOp(op)) { BinaryOperator::Opcode lop = symIntExpr->getOpcode(); if (BinaryOperator::isAdditiveOp(lop)) { // resultTy may not be the best type to convert to, but it's // probably the best choice in expressions with mixed type // (such as x+1U+2LL). The rules for implicit conversions should // choose a reasonable type to preserve the expression, and will // at least match how the value is going to be used. const llvm::APSInt &first = BasicVals.Convert(resultTy, symIntExpr->getRHS()); const llvm::APSInt &second = BasicVals.Convert(resultTy, rhsInt->getValue()); const llvm::APSInt *newRHS; if (lop == op) newRHS = BasicVals.evalAPSInt(BO_Add, first, second); else newRHS = BasicVals.evalAPSInt(BO_Sub, first, second); return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy); } } // Otherwise, make a SymExprVal out of the expression. return MakeSymIntVal(symIntExpr, op, rhsInt->getValue(), resultTy); } case nonloc::ConcreteIntKind: { const nonloc::ConcreteInt& lhsInt = cast<nonloc::ConcreteInt>(lhs); // Is the RHS a symbol we can simplify? // FIXME: This was mostly copy/pasted from the LHS-is-a-symbol case. if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) { SymbolRef RSym = srhs->getSymbol(); if (RSym->getType(Context)->isIntegerType()) { if (const llvm::APSInt *Constant = state->getSymVal(RSym)) { // The symbol evaluates to a constant. const llvm::APSInt *rhs_I; if (BinaryOperator::isRelationalOp(op)) rhs_I = &BasicVals.Convert(lhsInt.getValue(), *Constant); else rhs_I = &BasicVals.Convert(resultTy, *Constant); rhs = nonloc::ConcreteInt(*rhs_I); } } } if (isa<nonloc::ConcreteInt>(rhs)) { return lhsInt.evalBinOp(*this, op, cast<nonloc::ConcreteInt>(rhs)); } else { const llvm::APSInt& lhsValue = lhsInt.getValue(); // Swap the left and right sides and flip the operator if doing so // allows us to better reason about the expression (this is a form // of expression canonicalization). // While we're at it, catch some special cases for non-commutative ops. NonLoc tmp = rhs; rhs = lhs; lhs = tmp; switch (op) { case BO_LT: case BO_GT: case BO_LE: case BO_GE: op = ReverseComparison(op); continue; case BO_EQ: case BO_NE: case BO_Add: case BO_Mul: case BO_And: case BO_Xor: case BO_Or: continue; case BO_Shr: if (lhsValue.isAllOnesValue() && lhsValue.isSigned()) // At this point lhs and rhs have been swapped. return rhs; // FALL-THROUGH case BO_Shl: if (lhsValue == 0) // At this point lhs and rhs have been swapped. return rhs; return generateUnknownVal(state, op, lhs, rhs, resultTy); default: return generateUnknownVal(state, op, lhs, rhs, resultTy); } } } case nonloc::SymbolValKind: { nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs); SymbolRef Sym = slhs->getSymbol(); QualType lhsType = Sym->getType(Context); // The conversion type is usually the result type, but not in the case // of relational expressions. QualType conversionType = resultTy; if (BinaryOperator::isRelationalOp(op)) conversionType = lhsType; // Does the symbol simplify to a constant? If so, "fold" the constant // by setting 'lhs' to a ConcreteInt and try again. if (lhsType->isIntegerType()) if (const llvm::APSInt *Constant = state->getSymVal(Sym)) { // The symbol evaluates to a constant. If necessary, promote the // folded constant (LHS) to the result type. const llvm::APSInt &lhs_I = BasicVals.Convert(conversionType, *Constant); lhs = nonloc::ConcreteInt(lhs_I); // Also promote the RHS (if necessary). // For shifts, it is not necessary to promote the RHS. if (BinaryOperator::isShiftOp(op)) continue; // Other operators: do an implicit conversion. This shouldn't be // necessary once we support truncation/extension of symbolic values. if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){ rhs = nonloc::ConcreteInt(BasicVals.Convert(conversionType, rhs_I->getValue())); } continue; } // Is the RHS a symbol we can simplify? if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) { SymbolRef RSym = srhs->getSymbol(); if (RSym->getType(Context)->isIntegerType()) { if (const llvm::APSInt *Constant = state->getSymVal(RSym)) { // The symbol evaluates to a constant. const llvm::APSInt &rhs_I = BasicVals.Convert(conversionType, *Constant); rhs = nonloc::ConcreteInt(rhs_I); } } } if (isa<nonloc::ConcreteInt>(rhs)) { return MakeSymIntVal(slhs->getSymbol(), op, cast<nonloc::ConcreteInt>(rhs).getValue(), resultTy); } return generateUnknownVal(state, op, lhs, rhs, resultTy); } } } }
uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) { // The value in a relocatable COFF object is the offset. return Sym.getValue(); }
bool SectionRef::containsSymbol(SymbolRef S) const { section_iterator SymSec = getObject()->section_end(); if (S.getSection(SymSec)) return false; return *this == *SymSec; }
const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state, const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt& Int) { assert(BinaryOperator::isComparisonOp(op) && "Non-comparison ops should be rewritten as comparisons to zero."); // We only handle simple comparisons of the form "$sym == constant" // or "($sym+constant1) == constant2". // The adjustment is "constant1" in the above expression. It's used to // "slide" the solution range around for modular arithmetic. For example, // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to // the subclasses of SimpleConstraintManager to handle the adjustment. llvm::APSInt Adjustment; // First check if the LHS is a simple symbol reference. SymbolRef Sym = dyn_cast<SymbolData>(LHS); if (Sym) { Adjustment = 0; } else { // Next, see if it's a "($sym+constant1)" expression. const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS); // We don't handle "($sym1+$sym2)". // Give up and assume the constraint is feasible. if (!SE) return state; // We don't handle "(<expr>+constant1)". // Give up and assume the constraint is feasible. Sym = dyn_cast<SymbolData>(SE->getLHS()); if (!Sym) return state; // Get the constant out of the expression "($sym+constant1)". switch (SE->getOpcode()) { case BO_Add: Adjustment = SE->getRHS(); break; case BO_Sub: Adjustment = -SE->getRHS(); break; default: // We don't handle non-additive operators. // Give up and assume the constraint is feasible. return state; } } // FIXME: This next section is a hack. It silently converts the integers to // be of the same type as the symbol, which is not always correct. Really the // comparisons should be performed using the Int's type, then mapped back to // the symbol's range of values. GRStateManager &StateMgr = state->getStateManager(); ASTContext &Ctx = StateMgr.getContext(); QualType T = Sym->getType(Ctx); assert(T->isIntegerType() || Loc::IsLocType(T)); unsigned bitwidth = Ctx.getTypeSize(T); bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T); // Convert the adjustment. Adjustment.setIsUnsigned(isSymUnsigned); Adjustment.extOrTrunc(bitwidth); // Convert the right-hand side integer. llvm::APSInt ConvertedInt(Int, isSymUnsigned); ConvertedInt.extOrTrunc(bitwidth); switch (op) { default: // No logic yet for other operators. Assume the constraint is feasible. return state; case BO_EQ: return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment); case BO_NE: return AssumeSymNE(state, Sym, ConvertedInt, Adjustment); case BO_GT: return AssumeSymGT(state, Sym, ConvertedInt, Adjustment); case BO_GE: return AssumeSymGE(state, Sym, ConvertedInt, Adjustment); case BO_LT: return AssumeSymLT(state, Sym, ConvertedInt, Adjustment); case BO_LE: return AssumeSymLE(state, Sym, ConvertedInt, Adjustment); } // end switch }
Section* BinObject::AppendSection(llvm::StringRef name, SourceLocation source, Diagnostic& diags) { bool bss = (name == ".bss"); bool code = (name == ".text"); Section* section = new Section(name, code, bss, source); m_object.AppendSection(std::auto_ptr<Section>(section)); // Initialize section data and symbols. std::auto_ptr<BinSection> bsd(new BinSection()); SymbolRef start = m_object.getSymbol(("section."+name+".start").str()); if (start->okToDeclare(Symbol::EXTERN)) { start->Declare(Symbol::EXTERN); start->setDeclSource(source); } start->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::START))); SymbolRef vstart = m_object.getSymbol(("section."+name+".vstart").str()); if (vstart->okToDeclare(Symbol::EXTERN)) { vstart->Declare(Symbol::EXTERN); vstart->setDeclSource(source); } vstart->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::VSTART))); SymbolRef length = m_object.getSymbol(("section."+name+".length").str()); if (length->okToDeclare(Symbol::EXTERN)) { length->Declare(Symbol::EXTERN); length->setDeclSource(source); } length->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::LENGTH))); section->AddAssocData(std::auto_ptr<BinSection>(bsd.release())); return section; }